From 2dc435464873095fa13ec827e1f5f8246ba68b88 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 06:57:37 +0400 Subject: [PATCH 01/40] Add module KernAux::Multiboot2 --- bindings/ruby/ext/default/main.c | 9 ++++++--- bindings/ruby/ext/default/main.h | 3 +++ bindings/ruby/ext/default/multiboot2.c | 13 +++++++++++++ bindings/ruby/lib/kernaux.rb | 2 ++ bindings/ruby/lib/kernaux/multiboot2.rb | 11 +++++++++++ 5 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 bindings/ruby/ext/default/multiboot2.c create mode 100644 bindings/ruby/lib/kernaux/multiboot2.rb diff --git a/bindings/ruby/ext/default/main.c b/bindings/ruby/ext/default/main.c index 2578858d..8dddd741 100644 --- a/bindings/ruby/ext/default/main.c +++ b/bindings/ruby/ext/default/main.c @@ -24,11 +24,14 @@ void Init_default() #ifdef KERNAUX_VERSION_WITH_CMDLINE init_cmdline(); -#endif // KERNAUX_VERSION_WITH_CMDLINE +#endif +#ifdef KERNAUX_VERSION_WITH_MULTIBOOT2 + init_multiboot2(); +#endif #ifdef KERNAUX_VERSION_WITH_NTOA init_ntoa(); -#endif // KERNAUX_VERSION_WITH_NTOA +#endif #ifdef KERNAUX_VERSION_WITH_PRINTF init_printf(); -#endif // KERNAUX_VERSION_WITH_PRINTF +#endif } diff --git a/bindings/ruby/ext/default/main.h b/bindings/ruby/ext/default/main.h index 74d21872..562dcf7a 100644 --- a/bindings/ruby/ext/default/main.h +++ b/bindings/ruby/ext/default/main.h @@ -18,6 +18,9 @@ void init_assert(); #ifdef KERNAUX_VERSION_WITH_CMDLINE void init_cmdline(); #endif // KERNAUX_VERSION_WITH_CMDLINE +#ifdef KERNAUX_VERSION_WITH_MULTIBOOT2 +void init_multiboot2(); +#endif #ifdef KERNAUX_VERSION_WITH_NTOA void init_ntoa(); #endif // KERNAUX_VERSION_WITH_NTOA diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c new file mode 100644 index 00000000..d062b9ac --- /dev/null +++ b/bindings/ruby/ext/default/multiboot2.c @@ -0,0 +1,13 @@ +#include "main.h" + +#ifdef KERNAUX_VERSION_WITH_MULTIBOOT2 + +VALUE rb_KernAux_Multiboot2 = Qnil; + +void init_multiboot2() +{ + rb_gc_register_mark_object(rb_KernAux_Multiboot2 = + rb_define_module_under(rb_KernAux, "Multiboot2")); +} + +#endif diff --git a/bindings/ruby/lib/kernaux.rb b/bindings/ruby/lib/kernaux.rb index 9b356c90..0a338f5f 100644 --- a/bindings/ruby/lib/kernaux.rb +++ b/bindings/ruby/lib/kernaux.rb @@ -17,3 +17,5 @@ module KernAux require_relative 'kernaux/cmdline' require_relative 'kernaux/errors' require_relative 'kernaux/ntoa' + +require_relative 'kernaux/multiboot2' diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb new file mode 100644 index 00000000..3e4a00da --- /dev/null +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module KernAux + ## + # Multiboot 2 utils. + # + # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html + # + module Multiboot2 + end +end From 80eb8906529cc1ba263896804e1a2adc327967ce Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:09:08 +0400 Subject: [PATCH 02/40] Add method KernAux::Multiboot2::Header#magic --- bindings/ruby/ext/default/multiboot2.c | 63 +++++++++++++++++++- bindings/ruby/lib/kernaux/multiboot2.rb | 76 +++++++++++++++++++++++++ 2 files changed, 138 insertions(+), 1 deletion(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index d062b9ac..8877fb80 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -1,13 +1,74 @@ #include "main.h" +#include + #ifdef KERNAUX_VERSION_WITH_MULTIBOOT2 -VALUE rb_KernAux_Multiboot2 = Qnil; +#define RBNSMDL rb_KernAux_Multiboot2 +#define RBNS(s) rb_KernAux_Multiboot2_##s + +#define ENSURE_BASE_SIZE(data, Type) do { \ + const long len = RSTRING_LEN(data); \ + if (len < 0 || (size_t)len <= sizeof(struct KernAux_Multiboot2_##Type)) { \ + return Qnil; \ + } \ +} while (0) + +VALUE RBNSMDL = Qnil; // KernAux::Multiboot2 +VALUE RBNS(BaseSizeError) = Qnil; // KernAux::Multiboot2::BaseSizeError +VALUE RBNS(InvalidError) = Qnil; // KernAux::Multiboot2::InvalidError +VALUE RBNS(Struct) = Qnil; // KernAux::Multiboot2::Struct +VALUE RBNS(Header) = Qnil; // KernAux::Multiboot2::Header + +/** + * Return the magic field of the Multiboot 2 header. + * + * @return [nil, Integer] + * + * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + */ +// KernAux::Multiboot2::Header#magic +static VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self); void init_multiboot2() { + // KernAux::Multiboot2 rb_gc_register_mark_object(rb_KernAux_Multiboot2 = rb_define_module_under(rb_KernAux, "Multiboot2")); + + // KernAux::Multiboot2::BaseSizeError + rb_gc_register_mark_object(rb_KernAux_Multiboot2_BaseSizeError = + rb_define_class_under( + rb_KernAux_Multiboot2, "BaseSizeError", rb_KernAux_Error)); + + // KernAux::Multiboot2::InvalidError + rb_gc_register_mark_object(rb_KernAux_Multiboot2_InvalidError = + rb_define_class_under( + rb_KernAux_Multiboot2, "InvalidError", rb_KernAux_Error)); + + // KernAux::Multiboot2::Struct + rb_gc_register_mark_object(rb_KernAux_Multiboot2_Struct = + rb_define_class_under( + rb_KernAux_Multiboot2, "Struct", rb_cObject)); + + // KernAux::Multiboot2::Header + rb_gc_register_mark_object(rb_KernAux_Multiboot2_Header = + rb_define_class_under( + rb_KernAux_Multiboot2, "Header", rb_KernAux_Multiboot2_Struct)); + rb_define_method(rb_KernAux_Multiboot2_Header, "magic", + rb_KernAux_Multiboot2_Header_magic, 0); +} + +// KernAux::Multiboot2::Header#magic +VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + const struct KernAux_Multiboot2_Header *const multiboot2_header = + (const struct KernAux_Multiboot2_Header*) + StringValuePtr(data); + ENSURE_BASE_SIZE(data, Header); + KERNAUX_CAST_CONST(unsigned long, magic, multiboot2_header->magic); + return ULONG2NUM(magic); } #endif diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 3e4a00da..f71b08ef 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -7,5 +7,81 @@ module KernAux # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html # module Multiboot2 + ## + # Raised when trying to create a Multiboot 2 structure + # which is shorter than even it's base. + # + # @see Struct#enough! + # + class BaseSizeError < Error; end + + ## + # Raised when an invalid Multiboot 2 structure requested to be valid. + # + # @see Struct#valid! + # + class InvalidError < Error; end + + ## + # The base class for any Multiboot 2 structure. + # + class Struct + def initialize(data) + @data = String data + end + + ## + # Freeze the structure and it's underlying data. + # + def freeze + @data.freeze + super + nil + end + + def enough? + raise NotImplementedError, "#{self.class}#enough?" + end + + def valid? + raise NotImplementedError, "#{self.class}#valid?" + end + + ## + # @raise [BaseSizeError] the structure size is too small + # + def enough! + raise BaseSizeError, 'The structure size is too small' unless enough? + end + + ## + # @raise [BaseSizeError] the structure size is too small + # @raise [InvalidError] the structure is invalid + # + def valid! + enough! + raise InvalidError, 'The structure is invalid' unless valid? + end + end + + ## + # Multiboot 2 header. + # + # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-layout + # + class Header < Struct + ## + # Header magic number. + # + # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + # + MAGIC = 0xe85250d6 + + def initialize(data) + super + # TODO: use some const + raise BaseSizeError, 'Too short base' unless @data.bytesize < 16 + end + end end end From 117ca34e3413cedb936856183ffc8dd877f4c27a Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:21:39 +0400 Subject: [PATCH 03/40] Add method KernAux::Version.with_multiboot2? --- bindings/ruby/ext/default/version.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/bindings/ruby/ext/default/version.c b/bindings/ruby/ext/default/version.c index c4507d77..0cf6b818 100644 --- a/bindings/ruby/ext/default/version.c +++ b/bindings/ruby/ext/default/version.c @@ -1,6 +1,7 @@ #include "main.h" static VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self); +static VALUE rb_KernAux_Version_with_multiboot2QN(VALUE self); static VALUE rb_KernAux_Version_with_ntoaQN(VALUE self); static VALUE rb_KernAux_Version_with_printfQN(VALUE self); @@ -13,6 +14,8 @@ void init_version() rb_define_singleton_method(rb_KernAux_Version, "with_cmdline?", rb_KernAux_Version_with_cmdlineQN, 0); + rb_define_singleton_method(rb_KernAux_Version, "with_multiboot2?", + rb_KernAux_Version_with_multiboot2QN, 0); rb_define_singleton_method(rb_KernAux_Version, "with_ntoa?", rb_KernAux_Version_with_ntoaQN, 0); rb_define_singleton_method(rb_KernAux_Version, "with_printf?", @@ -28,6 +31,15 @@ VALUE rb_KernAux_Version_with_cmdlineQN(VALUE self) #endif } +VALUE rb_KernAux_Version_with_multiboot2QN(VALUE self) +{ +#ifdef KERNAUX_VERSION_WITH_MULTIBOOT2 + return Qtrue; +#else + return Qfalse; +#endif +} + VALUE rb_KernAux_Version_with_ntoaQN(VALUE self) { #ifdef KERNAUX_VERSION_WITH_NTOA From 4fa6c312600dcdf18dfa92c76e95a72288cb32a3 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:32:58 +0400 Subject: [PATCH 04/40] Improve code, fix bug, add tests --- bindings/ruby/ext/default/multiboot2.c | 22 ++++++++++--------- bindings/ruby/lib/kernaux/multiboot2.rb | 2 +- .../lib/kernaux/multiboot2/header_spec.rb | 20 +++++++++++++++++ 3 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 8877fb80..fe551475 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -7,12 +7,17 @@ #define RBNSMDL rb_KernAux_Multiboot2 #define RBNS(s) rb_KernAux_Multiboot2_##s -#define ENSURE_BASE_SIZE(data, Type) do { \ - const long len = RSTRING_LEN(data); \ - if (len < 0 || (size_t)len <= sizeof(struct KernAux_Multiboot2_##Type)) { \ - return Qnil; \ - } \ -} while (0) +#define EXTRACT_BASE_PTR(Type, name, data) \ + const struct KernAux_Multiboot2_##Type *const name = \ + (const struct KernAux_Multiboot2_##Type*) \ + StringValuePtr(data); \ + do { \ + const long len = RSTRING_LEN(data); \ + if (len < 0) return Qnil; \ + if ((size_t)len < sizeof(struct KernAux_Multiboot2_##Type)) { \ + return Qnil; \ + } \ + } while (0) VALUE RBNSMDL = Qnil; // KernAux::Multiboot2 VALUE RBNS(BaseSizeError) = Qnil; // KernAux::Multiboot2::BaseSizeError @@ -63,10 +68,7 @@ void init_multiboot2() VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self) { VALUE data = rb_ivar_get(self, rb_intern("@data")); - const struct KernAux_Multiboot2_Header *const multiboot2_header = - (const struct KernAux_Multiboot2_Header*) - StringValuePtr(data); - ENSURE_BASE_SIZE(data, Header); + EXTRACT_BASE_PTR(Header, multiboot2_header, data); KERNAUX_CAST_CONST(unsigned long, magic, multiboot2_header->magic); return ULONG2NUM(magic); } diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index f71b08ef..62764b0e 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -80,7 +80,7 @@ class Header < Struct def initialize(data) super # TODO: use some const - raise BaseSizeError, 'Too short base' unless @data.bytesize < 16 + raise BaseSizeError, 'Too short base' if @data.bytesize < 16 end end end diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb new file mode 100644 index 00000000..8ac4381b --- /dev/null +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +require 'spec_helper' + +if KernAux::Version.with_multiboot2? + RSpec.describe KernAux::Multiboot2::Header do + subject(:multiboot2_header) { described_class.new data } + + let :data do + "\xd6\x50\x52\xe8" + "\x00" * 12 + end + + describe '#magic' do + subject(:magic) { multiboot2_header.magic } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal described_class::MAGIC } + end + end +end From e1272a1885712d89326c645fa4e27d4a186f3432 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:37:48 +0400 Subject: [PATCH 05/40] Add method KernAux::Multiboot2::Header#arch --- bindings/ruby/ext/default/multiboot2.c | 21 ++++++++++++++++++- .../lib/kernaux/multiboot2/header_spec.rb | 9 +++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index fe551475..39c0d511 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -32,9 +32,17 @@ VALUE RBNS(Header) = Qnil; // KernAux::Multiboot2::Header * * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields */ -// KernAux::Multiboot2::Header#magic static VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self); +/** + * Return the architecture field of the Multiboot 2 header. + * + * @return [nil, Integer] + * + * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + */ +static VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self); + void init_multiboot2() { // KernAux::Multiboot2 @@ -62,6 +70,8 @@ void init_multiboot2() rb_KernAux_Multiboot2, "Header", rb_KernAux_Multiboot2_Struct)); rb_define_method(rb_KernAux_Multiboot2_Header, "magic", rb_KernAux_Multiboot2_Header_magic, 0); + rb_define_method(rb_KernAux_Multiboot2_Header, "arch", + rb_KernAux_Multiboot2_Header_arch, 0); } // KernAux::Multiboot2::Header#magic @@ -73,4 +83,13 @@ VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self) return ULONG2NUM(magic); } +// KernAux::Multiboot2::Header#arch +VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Header, multiboot2_header, data); + KERNAUX_CAST_CONST(unsigned long, arch, multiboot2_header->arch); + return ULONG2NUM(arch); +} + #endif diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 8ac4381b..1e39b7fd 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -7,7 +7,7 @@ subject(:multiboot2_header) { described_class.new data } let :data do - "\xd6\x50\x52\xe8" + "\x00" * 12 + "\xd6\x50\x52\xe8\x04\x00\x00\x00" + "\x00" * 8 end describe '#magic' do @@ -16,5 +16,12 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } end + + describe '#arch' do + subject(:arch) { multiboot2_header.arch } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 4 } + end end end From 85ba7eb8a2114649a88f8d7739161f33e36f19cb Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:40:55 +0400 Subject: [PATCH 06/40] Add method KernAux::Multiboot2::Header#arch_name --- bindings/ruby/lib/kernaux/multiboot2.rb | 11 +++++++++++ .../ruby/spec/lib/kernaux/multiboot2/header_spec.rb | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 62764b0e..0eeaff08 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -77,11 +77,22 @@ class Header < Struct # MAGIC = 0xe85250d6 + ARCH = { 0 => :i386, 4 => :mips32 }.freeze + def initialize(data) super # TODO: use some const raise BaseSizeError, 'Too short base' if @data.bytesize < 16 end + + ## + # Return the architecture field of the Multiboot 2 header. + # + # @return [Symbol] + # + # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + # + def arch_name = ARCH[arch] end end end diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 1e39b7fd..cb032728 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -23,5 +23,12 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal 4 } end + + describe '#arch_name' do + subject(:arch_name) { multiboot2_header.arch_name } + + it { is_expected.to be_instance_of Symbol } + it { is_expected.to equal :mips32 } + end end end From 745227dcf69d5775c12f77418981e03e33a0bc4f Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:42:40 +0400 Subject: [PATCH 07/40] Improve specs --- bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index cb032728..28d77d13 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -7,9 +7,12 @@ subject(:multiboot2_header) { described_class.new data } let :data do - "\xd6\x50\x52\xe8\x04\x00\x00\x00" + "\x00" * 8 + [magic_data, arch_data, "\x00" * 8].join.freeze end + let(:magic_data) { "\xd6\x50\x52\xe8" } + let(:arch_data) { "\x04\x00\x00\x00" } + describe '#magic' do subject(:magic) { multiboot2_header.magic } From be00fedcf9d2c5573199d81fb37db5c653f75da3 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:51:37 +0400 Subject: [PATCH 08/40] Add more tests --- .../lib/kernaux/multiboot2/header_spec.rb | 62 +++++++++++++++++-- 1 file changed, 57 insertions(+), 5 deletions(-) diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 28d77d13..1e328fb0 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -7,31 +7,83 @@ subject(:multiboot2_header) { described_class.new data } let :data do - [magic_data, arch_data, "\x00" * 8].join.freeze + [ + [Integer(magic_data)].pack('I'), + [Integer(arch_data)].pack('I'), + "\x00" * 8, + ].join.freeze end - let(:magic_data) { "\xd6\x50\x52\xe8" } - let(:arch_data) { "\x04\x00\x00\x00" } + let(:magic_data) { described_class::MAGIC } + let(:arch_data) { 0 } describe '#magic' do subject(:magic) { multiboot2_header.magic } it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } + + context 'when magic data is zero' do + let(:magic_data) { 0 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal magic_data } + end + + context 'when magic data is some other value' do + let(:magic_data) { 0x1234abcd } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal magic_data } + end end describe '#arch' do subject(:arch) { multiboot2_header.arch } it { is_expected.to be_instance_of Integer } - it { is_expected.to equal 4 } + it { is_expected.to equal arch_data } + + context 'when arch data is zero' do + let(:arch_data) { 0 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal arch_data } + end + + context 'when arch data is some other value' do + let(:arch_data) { 0x1234abcd } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal arch_data } + end end describe '#arch_name' do subject(:arch_name) { multiboot2_header.arch_name } it { is_expected.to be_instance_of Symbol } - it { is_expected.to equal :mips32 } + it { is_expected.to equal described_class::ARCH.fetch arch_data } + + context 'when arch is i386' do + let(:arch_data) { 0 } + + it { is_expected.to be_instance_of Symbol } + it { is_expected.to equal :i386 } + end + + context 'when arch is MIPS32' do + let(:arch_data) { 4 } + + it { is_expected.to be_instance_of Symbol } + it { is_expected.to equal :mips32 } + end + + context 'when arch data is some other value' do + let(:arch_data) { 0x1234abcd } + + it { is_expected.to equal nil } + end end end end From e3f88e9c7c21e8dcd73bfc65e11f9e320908b6ba Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:53:15 +0400 Subject: [PATCH 09/40] Fix docs --- bindings/ruby/ext/default/printf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/ruby/ext/default/printf.c b/bindings/ruby/ext/default/printf.c index b2785b6c..4a62f71d 100644 --- a/bindings/ruby/ext/default/printf.c +++ b/bindings/ruby/ext/default/printf.c @@ -6,7 +6,7 @@ #ifdef KERNAUX_VERSION_WITH_PRINTF /** - * Typical `printf`. + * Typical **printf**. * * @param format [String] format string * @return [String] formatted output From 21419a5990e6ce584282bf1c5a4b66c3ef5592a9 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:54:50 +0400 Subject: [PATCH 10/40] Add docs --- bindings/ruby/lib/kernaux/multiboot2.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 0eeaff08..6257e3d6 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -77,6 +77,12 @@ class Header < Struct # MAGIC = 0xe85250d6 + ## + # Header architecture field values. + # + # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + # @see #arch_name + # ARCH = { 0 => :i386, 4 => :mips32 }.freeze def initialize(data) @@ -91,6 +97,7 @@ def initialize(data) # @return [Symbol] # # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + # @see ARCH # def arch_name = ARCH[arch] end From 37346c7439bd1cf045ff8a422c791acf90acaf66 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 08:56:39 +0400 Subject: [PATCH 11/40] Remove unnecessary code --- bindings/ruby/lib/kernaux/multiboot2.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 6257e3d6..6885901b 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -85,12 +85,6 @@ class Header < Struct # ARCH = { 0 => :i386, 4 => :mips32 }.freeze - def initialize(data) - super - # TODO: use some const - raise BaseSizeError, 'Too short base' if @data.bytesize < 16 - end - ## # Return the architecture field of the Multiboot 2 header. # From 4976aa955a9f1c225bab9c1b01b9e57b6fd8e05d Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 09:04:06 +0400 Subject: [PATCH 12/40] Add method KernAux::Multiboot2::Header#total_size --- bindings/ruby/ext/default/multiboot2.c | 19 +++++++++++++ .../lib/kernaux/multiboot2/header_spec.rb | 27 +++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 39c0d511..1a89fb8a 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -43,6 +43,13 @@ static VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self); */ static VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self); +/** + * Return the total size (length) field of the Multiboot 2 header. + * + * @return [nil, Integer] + */ +static VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self); + void init_multiboot2() { // KernAux::Multiboot2 @@ -72,6 +79,8 @@ void init_multiboot2() rb_KernAux_Multiboot2_Header_magic, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "arch", rb_KernAux_Multiboot2_Header_arch, 0); + rb_define_method(rb_KernAux_Multiboot2_Header, "total_size", + rb_KernAux_Multiboot2_Header_total_size, 0); } // KernAux::Multiboot2::Header#magic @@ -92,4 +101,14 @@ VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self) return ULONG2NUM(arch); } +// KernAux::Multiboot2::Header#total_size +VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Header, multiboot2_header, data); + KERNAUX_CAST_CONST(unsigned long, total_size, + multiboot2_header->total_size); + return ULONG2NUM(total_size); +} + #endif diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 1e328fb0..ae52adbd 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -10,12 +10,14 @@ [ [Integer(magic_data)].pack('I'), [Integer(arch_data)].pack('I'), - "\x00" * 8, + [Integer(total_size_data)].pack('I'), + "\x00" * 4, ].join.freeze end let(:magic_data) { described_class::MAGIC } - let(:arch_data) { 0 } + let(:arch_data) { 0 } + let(:total_size_data) { 20 } describe '#magic' do subject(:magic) { multiboot2_header.magic } @@ -85,5 +87,26 @@ it { is_expected.to equal nil } end end + + describe '#total_size' do + subject(:total_size) { multiboot2_header.total_size } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal total_size_data } + + context 'when total size data is zero' do + let(:total_size_data) { 0 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal total_size_data } + end + + context 'when total size data is some other value' do + let(:total_size_data) { 0x1234abcd } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal total_size_data } + end + end end end From c8dba1b5feed7024c852c8893595ddd356205306 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 09:06:17 +0400 Subject: [PATCH 13/40] Freeze --- bindings/ruby/lib/kernaux/multiboot2.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 6885901b..88bb323d 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -26,8 +26,9 @@ class InvalidError < Error; end # The base class for any Multiboot 2 structure. # class Struct - def initialize(data) + def initialize(data = '') @data = String data + freeze if @data.frozen? end ## From cbf0eddcc9fbd5fe855802c507935529a6e91cde Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 09:14:15 +0400 Subject: [PATCH 14/40] Rename "/common/" to "/fixtures/" --- bindings/mruby/test/cmdline.rb | 4 ++-- bindings/mruby/test/sprintf.rb | 6 +++--- .../ruby/spec/lib/kernaux/cmdline_spec.rb | 4 ++-- .../ruby/spec/lib/kernaux/sprintf_spec.rb | 6 +++--- {common => fixtures}/cmdline.yml | 0 {common => fixtures}/printf.yml | 0 {common => fixtures}/printf_fmt.yml | 0 {common => fixtures}/printf_orig.yml | 0 tests/Makefile.am | 20 +++++++++---------- 9 files changed, 20 insertions(+), 20 deletions(-) rename {common => fixtures}/cmdline.yml (100%) rename {common => fixtures}/printf.yml (100%) rename {common => fixtures}/printf_fmt.yml (100%) rename {common => fixtures}/printf_orig.yml (100%) diff --git a/bindings/mruby/test/cmdline.rb b/bindings/mruby/test/cmdline.rb index 1a305f15..c24536c0 100644 --- a/bindings/mruby/test/cmdline.rb +++ b/bindings/mruby/test/cmdline.rb @@ -70,8 +70,8 @@ def test_cmdline(str, expected) end end - assert 'usign common tests' do - cmdline_yml = File.expand_path('../../../../common/cmdline.yml', __FILE__) + assert 'usign fixtures' do + cmdline_yml = File.expand_path('../../../../fixtures/cmdline.yml', __FILE__) YAML.load(File.read(cmdline_yml)).each do |test| escape_str = lambda do |str| diff --git a/bindings/mruby/test/sprintf.rb b/bindings/mruby/test/sprintf.rb index d656b5ab..affabf1f 100644 --- a/bindings/mruby/test/sprintf.rb +++ b/bindings/mruby/test/sprintf.rb @@ -65,12 +65,12 @@ end [ - ['', 'using regular tests'], - ['_orig', 'using original tests'], + ['', 'using regular fixtures'], + ['_orig', 'using original fixtures'], ].each do |(suffix, description)| assert description do printf_yml = - File.expand_path("../../../../common/printf#{suffix}.yml", __FILE__) + File.expand_path("../../../../fixtures/printf#{suffix}.yml", __FILE__) YAML.load(File.read(printf_yml)).each do |test| expected = test['result'] diff --git a/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb b/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb index b5d427b5..6a9f3408 100644 --- a/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb @@ -91,8 +91,8 @@ end end - context 'using common tests' do - cmdline_yml = File.expand_path('../../../../../common/cmdline.yml', __dir__) + context 'using fixtures' do + cmdline_yml = File.expand_path('../../../../../fixtures/cmdline.yml', __dir__) YAML.safe_load_file(cmdline_yml).each do |test| escape_str = lambda do |str| diff --git a/bindings/ruby/spec/lib/kernaux/sprintf_spec.rb b/bindings/ruby/spec/lib/kernaux/sprintf_spec.rb index c4593cbf..e172052b 100644 --- a/bindings/ruby/spec/lib/kernaux/sprintf_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/sprintf_spec.rb @@ -39,12 +39,12 @@ end [ - ['', 'using regular tests'], - ['_orig', 'using original tests'], + ['', 'using regular fixtures'], + ['_orig', 'using original fixtures'], ].each do |(suffix, description)| context description do printf_yml = File.expand_path( - "../../../../../common/printf#{suffix}.yml", + "../../../../../fixtures/printf#{suffix}.yml", __dir__, ) diff --git a/common/cmdline.yml b/fixtures/cmdline.yml similarity index 100% rename from common/cmdline.yml rename to fixtures/cmdline.yml diff --git a/common/printf.yml b/fixtures/printf.yml similarity index 100% rename from common/printf.yml rename to fixtures/printf.yml diff --git a/common/printf_fmt.yml b/fixtures/printf_fmt.yml similarity index 100% rename from common/printf_fmt.yml rename to fixtures/printf_fmt.yml diff --git a/common/printf_orig.yml b/fixtures/printf_orig.yml similarity index 100% rename from common/printf_orig.yml rename to fixtures/printf_orig.yml diff --git a/tests/Makefile.am b/tests/Makefile.am index 7db522c0..2f9d7bb0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -121,7 +121,7 @@ test_cmdline_gen_SOURCES = \ test_cmdline_gen.c \ cmdline_gen.py \ cmdline_gen.jinja \ - $(top_srcdir)/common/cmdline.yml \ + $(top_srcdir)/fixtures/cmdline.yml \ cmdline_test.h \ cmdline_test.c endif @@ -129,8 +129,8 @@ endif CLEANFILES += test_cmdline_gen.c -test_cmdline_gen.c: $(top_srcdir)/tests/cmdline_gen.py $(top_srcdir)/tests/cmdline_gen.jinja $(top_srcdir)/common/cmdline.yml - $(PYTHON) $(top_srcdir)/tests/cmdline_gen.py $(top_srcdir)/tests/cmdline_gen.jinja $(top_srcdir)/common/cmdline.yml test_cmdline_gen.c +test_cmdline_gen.c: $(top_srcdir)/tests/cmdline_gen.py $(top_srcdir)/tests/cmdline_gen.jinja $(top_srcdir)/fixtures/cmdline.yml + $(PYTHON) $(top_srcdir)/tests/cmdline_gen.py $(top_srcdir)/tests/cmdline_gen.jinja $(top_srcdir)/fixtures/cmdline.yml test_cmdline_gen.c ############ # test_elf # @@ -359,14 +359,14 @@ test_printf_fmt_gen_SOURCES = \ test_printf_fmt_gen.c \ printf_fmt_gen.py \ printf_fmt_gen.jinja \ - $(top_srcdir)/common/printf_fmt.yml + $(top_srcdir)/fixtures/printf_fmt.yml endif endif CLEANFILES += test_printf_fmt_gen.c -test_printf_fmt_gen.c: $(top_srcdir)/tests/printf_fmt_gen.py $(top_srcdir)/tests/printf_fmt_gen.jinja $(top_srcdir)/common/printf_fmt.yml - $(PYTHON) $(top_srcdir)/tests/printf_fmt_gen.py $(top_srcdir)/tests/printf_fmt_gen.jinja $(top_srcdir)/common/printf_fmt.yml test_printf_fmt_gen.c +test_printf_fmt_gen.c: $(top_srcdir)/tests/printf_fmt_gen.py $(top_srcdir)/tests/printf_fmt_gen.jinja $(top_srcdir)/fixtures/printf_fmt.yml + $(PYTHON) $(top_srcdir)/tests/printf_fmt_gen.py $(top_srcdir)/tests/printf_fmt_gen.jinja $(top_srcdir)/fixtures/printf_fmt.yml test_printf_fmt_gen.c ################### # test_printf_gen # @@ -381,15 +381,15 @@ test_printf_gen_SOURCES = \ test_printf_gen.c \ printf_gen.py \ printf_gen.jinja \ - $(top_srcdir)/common/printf.yml \ - $(top_srcdir)/common/printf_orig.yml + $(top_srcdir)/fixtures/printf.yml \ + $(top_srcdir)/fixtures/printf_orig.yml endif endif CLEANFILES += test_printf_gen.c -test_printf_gen.c: $(top_srcdir)/tests/printf_gen.py $(top_srcdir)/tests/printf_gen.jinja $(top_srcdir)/common/printf.yml $(top_srcdir)/common/printf_orig.yml - $(PYTHON) $(top_srcdir)/tests/printf_gen.py $(top_srcdir)/tests/printf_gen.jinja $(top_srcdir)/common/printf.yml $(top_srcdir)/common/printf_orig.yml test_printf_gen.c +test_printf_gen.c: $(top_srcdir)/tests/printf_gen.py $(top_srcdir)/tests/printf_gen.jinja $(top_srcdir)/fixtures/printf.yml $(top_srcdir)/fixtures/printf_orig.yml + $(PYTHON) $(top_srcdir)/tests/printf_gen.py $(top_srcdir)/tests/printf_gen.jinja $(top_srcdir)/fixtures/printf.yml $(top_srcdir)/fixtures/printf_orig.yml test_printf_gen.c #################### # test_units_human # From a62df01dfc717c3ca1530ec1f7be76bc8326f0a4 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 09:22:34 +0400 Subject: [PATCH 15/40] Move Multiboot 2 examples --- .../multiboot2_header_example0.h | 0 .../multiboot2_header_example1.h | 0 .../multiboot2_header_example2.h | 0 .../multiboot2_info_example0.h | 0 .../multiboot2_info_example1.h | 0 .../multiboot2_info_example2.h | 0 tests/Makefile.am | 32 +++++++++---------- tests/multiboot2_header_print0.c | 2 +- tests/multiboot2_header_print1.c | 2 +- tests/multiboot2_header_print2.c | 2 +- tests/multiboot2_info_print0.c | 2 +- tests/multiboot2_info_print1.c | 2 +- tests/multiboot2_info_print2.c | 2 +- tests/test_multiboot2_common_packing.c | 4 +-- tests/test_multiboot2_header_helpers.c | 4 +-- tests/test_multiboot2_info_helpers.c | 4 +-- tests/test_multiboot2_info_validation.c | 4 +-- 17 files changed, 30 insertions(+), 30 deletions(-) rename {tests => fixtures}/multiboot2_header_example0.h (100%) rename {tests => fixtures}/multiboot2_header_example1.h (100%) rename {tests => fixtures}/multiboot2_header_example2.h (100%) rename {tests => fixtures}/multiboot2_info_example0.h (100%) rename {tests => fixtures}/multiboot2_info_example1.h (100%) rename {tests => fixtures}/multiboot2_info_example2.h (100%) diff --git a/tests/multiboot2_header_example0.h b/fixtures/multiboot2_header_example0.h similarity index 100% rename from tests/multiboot2_header_example0.h rename to fixtures/multiboot2_header_example0.h diff --git a/tests/multiboot2_header_example1.h b/fixtures/multiboot2_header_example1.h similarity index 100% rename from tests/multiboot2_header_example1.h rename to fixtures/multiboot2_header_example1.h diff --git a/tests/multiboot2_header_example2.h b/fixtures/multiboot2_header_example2.h similarity index 100% rename from tests/multiboot2_header_example2.h rename to fixtures/multiboot2_header_example2.h diff --git a/tests/multiboot2_info_example0.h b/fixtures/multiboot2_info_example0.h similarity index 100% rename from tests/multiboot2_info_example0.h rename to fixtures/multiboot2_info_example0.h diff --git a/tests/multiboot2_info_example1.h b/fixtures/multiboot2_info_example1.h similarity index 100% rename from tests/multiboot2_info_example1.h rename to fixtures/multiboot2_info_example1.h diff --git a/tests/multiboot2_info_example2.h b/fixtures/multiboot2_info_example2.h similarity index 100% rename from tests/multiboot2_info_example2.h rename to fixtures/multiboot2_info_example2.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 2f9d7bb0..6796b1b9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,7 +14,7 @@ multiboot2_header_print0_LDADD = $(top_builddir)/libkernaux.la multiboot2_header_print0_SOURCES = \ main.c \ multiboot2_header_print0.c \ - multiboot2_header_example0.h + ../fixtures/multiboot2_header_example0.h endif ############################ @@ -27,7 +27,7 @@ multiboot2_header_print1_LDADD = $(top_builddir)/libkernaux.la multiboot2_header_print1_SOURCES = \ main.c \ multiboot2_header_print1.c \ - multiboot2_header_example1.h + ../fixtures/multiboot2_header_example1.h endif ############################ @@ -40,7 +40,7 @@ multiboot2_header_print2_LDADD = $(top_builddir)/libkernaux.la multiboot2_header_print2_SOURCES = \ main.c \ multiboot2_header_print2.c \ - multiboot2_header_example2.h + ../fixtures/multiboot2_header_example2.h endif ########################## @@ -53,7 +53,7 @@ multiboot2_info_print0_LDADD = $(top_builddir)/libkernaux.la multiboot2_info_print0_SOURCES = \ main.c \ multiboot2_info_print0.c \ - multiboot2_info_example0.h + ../fixtures/multiboot2_info_example0.h endif ########################## @@ -66,7 +66,7 @@ multiboot2_info_print1_LDADD = $(top_builddir)/libkernaux.la multiboot2_info_print1_SOURCES = \ main.c \ multiboot2_info_print1.c \ - multiboot2_info_example1.h + ../fixtures/multiboot2_info_example1.h endif ########################## @@ -79,7 +79,7 @@ multiboot2_info_print2_LDADD = $(top_builddir)/libkernaux.la multiboot2_info_print2_SOURCES = \ main.c \ multiboot2_info_print2.c \ - multiboot2_info_example2.h + ../fixtures/multiboot2_info_example2.h endif ################## @@ -190,8 +190,8 @@ test_multiboot2_common_packing_LDADD = $(top_builddir)/libkernaux.la test_multiboot2_common_packing_SOURCES = \ main.c \ test_multiboot2_common_packing.c \ - multiboot2_header_example2.h \ - multiboot2_info_example2.h + ../fixtures/multiboot2_header_example2.h \ + ../fixtures/multiboot2_info_example2.h endif ################################## @@ -204,8 +204,8 @@ test_multiboot2_header_helpers_LDADD = $(top_builddir)/libkernaux.la test_multiboot2_header_helpers_SOURCES = \ main.c \ test_multiboot2_header_helpers.c \ - multiboot2_header_example1.h \ - multiboot2_header_example2.h + ../fixtures/multiboot2_header_example1.h \ + ../fixtures/multiboot2_header_example2.h endif ################################ @@ -234,8 +234,8 @@ test_multiboot2_header_validation_LDADD = $(top_builddir)/libkernaux.la test_multiboot2_header_validation_SOURCES = \ main.c \ test_multiboot2_header_validation.c \ - multiboot2_header_example1.h \ - multiboot2_header_example2.h + ../fixtures/multiboot2_header_example1.h \ + ../fixtures/multiboot2_header_example2.h endif ################################ @@ -248,8 +248,8 @@ test_multiboot2_info_helpers_LDADD = $(top_builddir)/libkernaux.la test_multiboot2_info_helpers_SOURCES = \ main.c \ test_multiboot2_info_helpers.c \ - multiboot2_info_example1.h \ - multiboot2_info_example2.h + ../fixtures/multiboot2_info_example1.h \ + ../fixtures/multiboot2_info_example2.h endif ############################## @@ -278,8 +278,8 @@ test_multiboot2_info_validation_LDADD = $(top_builddir)/libkernaux.la test_multiboot2_info_validation_SOURCES = \ main.c \ test_multiboot2_info_validation.c \ - multiboot2_info_example1.h \ - multiboot2_info_example2.h + ../fixtures/multiboot2_info_example1.h \ + ../fixtures/multiboot2_info_example2.h endif ############# diff --git a/tests/multiboot2_header_print0.c b/tests/multiboot2_header_print0.c index 89836d3f..407e2218 100644 --- a/tests/multiboot2_header_print0.c +++ b/tests/multiboot2_header_print0.c @@ -12,7 +12,7 @@ #include #include -#include "multiboot2_header_example0.h" +#include "../fixtures/multiboot2_header_example0.h" static void my_putc(void *display KERNAUX_UNUSED, char c) { diff --git a/tests/multiboot2_header_print1.c b/tests/multiboot2_header_print1.c index 0eab3d22..fe16b403 100644 --- a/tests/multiboot2_header_print1.c +++ b/tests/multiboot2_header_print1.c @@ -12,7 +12,7 @@ #include #include -#include "multiboot2_header_example1.h" +#include "../fixtures/multiboot2_header_example1.h" static void my_putc(void *display KERNAUX_UNUSED, char c) { diff --git a/tests/multiboot2_header_print2.c b/tests/multiboot2_header_print2.c index 50b41bba..1d003864 100644 --- a/tests/multiboot2_header_print2.c +++ b/tests/multiboot2_header_print2.c @@ -12,7 +12,7 @@ #include #include -#include "multiboot2_header_example2.h" +#include "../fixtures/multiboot2_header_example2.h" static void my_putc(void *display KERNAUX_UNUSED, char c) { diff --git a/tests/multiboot2_info_print0.c b/tests/multiboot2_info_print0.c index 642a7aa1..ddcf46dd 100644 --- a/tests/multiboot2_info_print0.c +++ b/tests/multiboot2_info_print0.c @@ -12,7 +12,7 @@ #include #include -#include "multiboot2_info_example0.h" +#include "../fixtures/multiboot2_info_example0.h" static void my_putc(void *display KERNAUX_UNUSED, char c) { diff --git a/tests/multiboot2_info_print1.c b/tests/multiboot2_info_print1.c index 095821a0..8770af93 100644 --- a/tests/multiboot2_info_print1.c +++ b/tests/multiboot2_info_print1.c @@ -12,7 +12,7 @@ #include #include -#include "multiboot2_info_example1.h" +#include "../fixtures/multiboot2_info_example1.h" static void my_putc(void *display KERNAUX_UNUSED, char c) { diff --git a/tests/multiboot2_info_print2.c b/tests/multiboot2_info_print2.c index 30ed471d..8e0f1bf2 100644 --- a/tests/multiboot2_info_print2.c +++ b/tests/multiboot2_info_print2.c @@ -12,7 +12,7 @@ #include #include -#include "multiboot2_info_example2.h" +#include "../fixtures/multiboot2_info_example2.h" static void my_putc(void *display KERNAUX_UNUSED, char c) { diff --git a/tests/test_multiboot2_common_packing.c b/tests/test_multiboot2_common_packing.c index b54653f4..f9215fba 100644 --- a/tests/test_multiboot2_common_packing.c +++ b/tests/test_multiboot2_common_packing.c @@ -7,8 +7,8 @@ #include #include -#include "multiboot2_header_example2.h" -#include "multiboot2_info_example2.h" +#include "../fixtures/multiboot2_header_example2.h" +#include "../fixtures/multiboot2_info_example2.h" #define HEAD_SIZEOF1(type, inst, size) \ do { \ diff --git a/tests/test_multiboot2_header_helpers.c b/tests/test_multiboot2_header_helpers.c index 5af933d1..10d2aa1d 100644 --- a/tests/test_multiboot2_header_helpers.c +++ b/tests/test_multiboot2_header_helpers.c @@ -4,8 +4,8 @@ #include -#include "multiboot2_header_example1.h" -#include "multiboot2_header_example2.h" +#include "../fixtures/multiboot2_header_example1.h" +#include "../fixtures/multiboot2_header_example2.h" void test_main() { diff --git a/tests/test_multiboot2_info_helpers.c b/tests/test_multiboot2_info_helpers.c index 7a6c34eb..bd9592ea 100644 --- a/tests/test_multiboot2_info_helpers.c +++ b/tests/test_multiboot2_info_helpers.c @@ -7,8 +7,8 @@ #include -#include "multiboot2_info_example1.h" -#include "multiboot2_info_example2.h" +#include "../fixtures/multiboot2_info_example1.h" +#include "../fixtures/multiboot2_info_example2.h" #include diff --git a/tests/test_multiboot2_info_validation.c b/tests/test_multiboot2_info_validation.c index 45017566..0aebdf43 100644 --- a/tests/test_multiboot2_info_validation.c +++ b/tests/test_multiboot2_info_validation.c @@ -7,8 +7,8 @@ #include -#include "multiboot2_info_example1.h" -#include "multiboot2_info_example2.h" +#include "../fixtures/multiboot2_info_example1.h" +#include "../fixtures/multiboot2_info_example2.h" #include From 538eeac1557c2c57e15693fe2c6f267a35920992 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 09:26:38 +0400 Subject: [PATCH 16/40] Fix docs --- bindings/ruby/lib/kernaux/multiboot2.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 88bb323d..72bf6655 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -89,7 +89,7 @@ class Header < Struct ## # Return the architecture field of the Multiboot 2 header. # - # @return [Symbol] + # @return [nil, Symbol] # # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields # @see ARCH From 90644fa5196753873994a2b94bdea0c406e5520c Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 09:27:03 +0400 Subject: [PATCH 17/40] Fix code style --- bindings/ruby/spec/lib/kernaux/cmdline_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb b/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb index 6a9f3408..280d5041 100644 --- a/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/cmdline_spec.rb @@ -92,7 +92,8 @@ end context 'using fixtures' do - cmdline_yml = File.expand_path('../../../../../fixtures/cmdline.yml', __dir__) + cmdline_yml = + File.expand_path('../../../../../fixtures/cmdline.yml', __dir__) YAML.safe_load_file(cmdline_yml).each do |test| escape_str = lambda do |str| From e20b4dac0441e7f4b60a01083883dd39abccb4c8 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 16:31:00 +0400 Subject: [PATCH 18/40] Fix typo & test fixtures on CI --- .cirrus.yml | 2 +- .github/workflows/main.yml | 2 +- .openbsd.yml | 2 +- fixtures/Makefile.am | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index b05e32b5..41d3ee46 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -12,7 +12,7 @@ main_freebsd_task: - pip install --user Jinja2 PyYAML main_build_script: - ./autogen.sh - - ./configure --enable-debug --enable-checks-all CFLAGS='-O3' + - ./configure --enable-debug --enable-fixtures --enable-checks-all CFLAGS='-O3' - make - sudo make install main_test_script: diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 29622346..9e4175b2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -34,7 +34,7 @@ jobs: - name: autogen run: ./autogen.sh - name: configure - run: ./configure ${{matrix.debug}} --enable-checks --enable-checks-pthreads --enable-checks-python CC='${{matrix.cc}}' CFLAGS='${{matrix.opt}}' + run: ./configure ${{matrix.debug}} --enable-fixtures --enable-checks --enable-checks-pthreads --enable-checks-python CC='${{matrix.cc}}' CFLAGS='${{matrix.opt}}' - name: make run: make - name: check diff --git a/.openbsd.yml b/.openbsd.yml index cfd6ca31..e5838687 100644 --- a/.openbsd.yml +++ b/.openbsd.yml @@ -31,7 +31,7 @@ tasks: - build: | cd libkernaux ./autogen.sh - ./configure --enable-debug --enable-checks-all CFLAGS='-O3' + ./configure --enable-debug --enable-fixtures --enable-checks-all CFLAGS='-O3' make doas make install - test: | diff --git a/fixtures/Makefile.am b/fixtures/Makefile.am index 39b92e03..b04300f8 100644 --- a/fixtures/Makefile.am +++ b/fixtures/Makefile.am @@ -20,7 +20,7 @@ endif multiboot2_header_example0.bin: multiboot2_bin_examples_gen ./multiboot2_bin_examples_gen header 0 -multiboot2_header_example1.bin_examples_gen: multiboot2_bin +multiboot2_header_example1.bin: multiboot2_bin_examples_gen ./multiboot2_bin_examples_gen header 1 multiboot2_header_example2.bin: multiboot2_bin_examples_gen From 8cd09497c232b958bc2aa569c4a7160d841a26a2 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sat, 17 Dec 2022 17:51:50 +0400 Subject: [PATCH 19/40] Use fixtures in specs --- .../lib/kernaux/multiboot2/header_spec.rb | 90 +++---------------- 1 file changed, 13 insertions(+), 77 deletions(-) diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index ae52adbd..c8e45865 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -4,109 +4,45 @@ if KernAux::Version.with_multiboot2? RSpec.describe KernAux::Multiboot2::Header do - subject(:multiboot2_header) { described_class.new data } + subject(:multiboot2_header) { described_class.new fixture_data } - let :data do - [ - [Integer(magic_data)].pack('I'), - [Integer(arch_data)].pack('I'), - [Integer(total_size_data)].pack('I'), - "\x00" * 4, - ].join.freeze - end + let(:fixture) { 0 } + + let(:fixture_data) { File.read fixture_path } - let(:magic_data) { described_class::MAGIC } - let(:arch_data) { 0 } - let(:total_size_data) { 20 } + let :fixture_path do + File.expand_path( + "../../../../../../fixtures/multiboot2_header_example#{fixture}.bin", + __dir__ + ) + end describe '#magic' do subject(:magic) { multiboot2_header.magic } it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } - - context 'when magic data is zero' do - let(:magic_data) { 0 } - - it { is_expected.to be_instance_of Integer } - it { is_expected.to equal magic_data } - end - - context 'when magic data is some other value' do - let(:magic_data) { 0x1234abcd } - - it { is_expected.to be_instance_of Integer } - it { is_expected.to equal magic_data } - end end describe '#arch' do subject(:arch) { multiboot2_header.arch } it { is_expected.to be_instance_of Integer } - it { is_expected.to equal arch_data } - - context 'when arch data is zero' do - let(:arch_data) { 0 } - - it { is_expected.to be_instance_of Integer } - it { is_expected.to equal arch_data } - end - - context 'when arch data is some other value' do - let(:arch_data) { 0x1234abcd } - - it { is_expected.to be_instance_of Integer } - it { is_expected.to equal arch_data } - end + it { is_expected.to equal 0 } end describe '#arch_name' do subject(:arch_name) { multiboot2_header.arch_name } it { is_expected.to be_instance_of Symbol } - it { is_expected.to equal described_class::ARCH.fetch arch_data } - - context 'when arch is i386' do - let(:arch_data) { 0 } - - it { is_expected.to be_instance_of Symbol } - it { is_expected.to equal :i386 } - end - - context 'when arch is MIPS32' do - let(:arch_data) { 4 } - - it { is_expected.to be_instance_of Symbol } - it { is_expected.to equal :mips32 } - end - - context 'when arch data is some other value' do - let(:arch_data) { 0x1234abcd } - - it { is_expected.to equal nil } - end + it { is_expected.to equal :i386 } end describe '#total_size' do subject(:total_size) { multiboot2_header.total_size } it { is_expected.to be_instance_of Integer } - it { is_expected.to equal total_size_data } - - context 'when total size data is zero' do - let(:total_size_data) { 0 } - - it { is_expected.to be_instance_of Integer } - it { is_expected.to equal total_size_data } - end - - context 'when total size data is some other value' do - let(:total_size_data) { 0x1234abcd } - - it { is_expected.to be_instance_of Integer } - it { is_expected.to equal total_size_data } - end + it { is_expected.to equal 24 } end end end From e75ac1ba0acc0b1fb2acf4fb048d792cd0100921 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 09:55:30 +0400 Subject: [PATCH 20/40] Add method KernAux::Multiboot2::Header#enough? --- bindings/ruby/ext/default/multiboot2.c | 25 ++++++++++++++----- bindings/ruby/lib/kernaux/multiboot2.rb | 6 +++-- .../lib/kernaux/multiboot2/header_spec.rb | 13 ++++++++++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 1a89fb8a..34cf6d7b 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -7,15 +7,15 @@ #define RBNSMDL rb_KernAux_Multiboot2 #define RBNS(s) rb_KernAux_Multiboot2_##s -#define EXTRACT_BASE_PTR(Type, name, data) \ +#define EXTRACT_BASE_PTR(Type, name, data, Qnegresult) \ const struct KernAux_Multiboot2_##Type *const name = \ (const struct KernAux_Multiboot2_##Type*) \ StringValuePtr(data); \ do { \ const long len = RSTRING_LEN(data); \ - if (len < 0) return Qnil; \ + if (len < 0) return (Qnegresult); \ if ((size_t)len < sizeof(struct KernAux_Multiboot2_##Type)) { \ - return Qnil; \ + return (Qnegresult); \ } \ } while (0) @@ -25,6 +25,8 @@ VALUE RBNS(InvalidError) = Qnil; // KernAux::Multiboot2::InvalidError VALUE RBNS(Struct) = Qnil; // KernAux::Multiboot2::Struct VALUE RBNS(Header) = Qnil; // KernAux::Multiboot2::Header +static VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self); + /** * Return the magic field of the Multiboot 2 header. * @@ -75,6 +77,8 @@ void init_multiboot2() rb_gc_register_mark_object(rb_KernAux_Multiboot2_Header = rb_define_class_under( rb_KernAux_Multiboot2, "Header", rb_KernAux_Multiboot2_Struct)); + rb_define_method(rb_KernAux_Multiboot2_Header, "enough?", + rb_KernAux_Multiboot2_Header_enoughQN, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "magic", rb_KernAux_Multiboot2_Header_magic, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "arch", @@ -83,11 +87,20 @@ void init_multiboot2() rb_KernAux_Multiboot2_Header_total_size, 0); } +// KernAux::Multiboot2::Header#enough? +VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qfalse); + (void)multiboot2_header; // unused + return Qtrue; +} + // KernAux::Multiboot2::Header#magic VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self) { VALUE data = rb_ivar_get(self, rb_intern("@data")); - EXTRACT_BASE_PTR(Header, multiboot2_header, data); + EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qnil); KERNAUX_CAST_CONST(unsigned long, magic, multiboot2_header->magic); return ULONG2NUM(magic); } @@ -96,7 +109,7 @@ VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self) VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self) { VALUE data = rb_ivar_get(self, rb_intern("@data")); - EXTRACT_BASE_PTR(Header, multiboot2_header, data); + EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qnil); KERNAUX_CAST_CONST(unsigned long, arch, multiboot2_header->arch); return ULONG2NUM(arch); } @@ -105,7 +118,7 @@ VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self) VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self) { VALUE data = rb_ivar_get(self, rb_intern("@data")); - EXTRACT_BASE_PTR(Header, multiboot2_header, data); + EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qnil); KERNAUX_CAST_CONST(unsigned long, total_size, multiboot2_header->total_size); return ULONG2NUM(total_size); diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 72bf6655..d21948b6 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -8,8 +8,8 @@ module KernAux # module Multiboot2 ## - # Raised when trying to create a Multiboot 2 structure - # which is shorter than even it's base. + # Raised when a Multiboot 2 structure which is shorter than even it's base + # requested to be enough sized. # # @see Struct#enough! # @@ -53,6 +53,7 @@ def valid? # def enough! raise BaseSizeError, 'The structure size is too small' unless enough? + self end ## @@ -62,6 +63,7 @@ def enough! def valid! enough! raise InvalidError, 'The structure is invalid' unless valid? + self end end diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index c8e45865..7cd2508e 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -17,6 +17,19 @@ ) end + describe '#enough?' do + subject(:enough?) { multiboot2_header.enough? } + + it { is_expected.to equal true } + end + + describe '#enough!' do + subject(:enough!) { multiboot2_header.enough! } + + specify { expect { enough! }.not_to raise_error } + it { is_expected.to equal multiboot2_header } + end + describe '#magic' do subject(:magic) { multiboot2_header.magic } From 6e5513b889f74bd76dde600ecbcf9471a96170b9 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 09:59:41 +0400 Subject: [PATCH 21/40] Fix method KernAux::Multiboot2::Struct#freeze --- bindings/ruby/lib/kernaux/multiboot2.rb | 2 +- .../lib/kernaux/multiboot2/header_spec.rb | 20 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index d21948b6..b29b66e6 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -37,7 +37,7 @@ def initialize(data = '') def freeze @data.freeze super - nil + self end def enough? diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 7cd2508e..ebc245c0 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -17,6 +17,26 @@ ) end + describe '#freeze' do + subject(:freeze) { multiboot2_header.freeze } + + it { is_expected.to equal multiboot2_header } + + specify do + expect { freeze }.to \ + change { multiboot2_header.frozen? } + .from(false) + .to(true) + end + + specify do + expect { freeze }.to \ + change { fixture_data.frozen? } + .from(false) + .to(true) + end + end + describe '#enough?' do subject(:enough?) { multiboot2_header.enough? } From 8ece0aa08ec1719a5192842a8f0ed51db74d1b8e Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:06:51 +0400 Subject: [PATCH 22/40] Fix code style --- bindings/ruby/lib/kernaux/multiboot2.rb | 2 ++ bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb | 9 +++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index b29b66e6..0bc23bdc 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -53,6 +53,7 @@ def valid? # def enough! raise BaseSizeError, 'The structure size is too small' unless enough? + self end @@ -63,6 +64,7 @@ def enough! def valid! enough! raise InvalidError, 'The structure is invalid' unless valid? + self end end diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index ebc245c0..27a42e60 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -13,7 +13,7 @@ let :fixture_path do File.expand_path( "../../../../../../fixtures/multiboot2_header_example#{fixture}.bin", - __dir__ + __dir__, ) end @@ -24,16 +24,13 @@ specify do expect { freeze }.to \ - change { multiboot2_header.frozen? } + change(multiboot2_header, :frozen?) .from(false) .to(true) end specify do - expect { freeze }.to \ - change { fixture_data.frozen? } - .from(false) - .to(true) + expect { freeze }.to change(fixture_data, :frozen?).from(false).to(true) end end From a1c776eb18b33472a34ac45f933d76c9a0194530 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:12:17 +0400 Subject: [PATCH 23/40] Add method KernAux::Multiboot2::Header#valid? --- bindings/ruby/ext/default/multiboot2.c | 15 +++++++++++++++ .../spec/lib/kernaux/multiboot2/header_spec.rb | 13 +++++++++++++ 2 files changed, 28 insertions(+) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 34cf6d7b..093257eb 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -26,6 +26,7 @@ VALUE RBNS(Struct) = Qnil; // KernAux::Multiboot2::Struct VALUE RBNS(Header) = Qnil; // KernAux::Multiboot2::Header static VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self); +static VALUE rb_KernAux_Multiboot2_Header_validQN(VALUE self); /** * Return the magic field of the Multiboot 2 header. @@ -79,6 +80,8 @@ void init_multiboot2() rb_KernAux_Multiboot2, "Header", rb_KernAux_Multiboot2_Struct)); rb_define_method(rb_KernAux_Multiboot2_Header, "enough?", rb_KernAux_Multiboot2_Header_enoughQN, 0); + rb_define_method(rb_KernAux_Multiboot2_Header, "valid?", + rb_KernAux_Multiboot2_Header_validQN, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "magic", rb_KernAux_Multiboot2_Header_magic, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "arch", @@ -96,6 +99,18 @@ VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self) return Qtrue; } +// KernAux::Multiboot2::Header#valid? +VALUE rb_KernAux_Multiboot2_Header_validQN(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qfalse); + if (KernAux_Multiboot2_Header_is_valid(multiboot2_header)) { + return Qtrue; + } else { + return Qfalse; + } +} + // KernAux::Multiboot2::Header#magic VALUE rb_KernAux_Multiboot2_Header_magic(VALUE self) { diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 27a42e60..6a2323f7 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -40,6 +40,12 @@ it { is_expected.to equal true } end + describe '#valid?' do + subject(:valid?) { multiboot2_header.valid? } + + it { is_expected.to equal true } + end + describe '#enough!' do subject(:enough!) { multiboot2_header.enough! } @@ -47,6 +53,13 @@ it { is_expected.to equal multiboot2_header } end + describe '#valid!' do + subject(:valid!) { multiboot2_header.valid! } + + specify { expect { valid! }.not_to raise_error } + it { is_expected.to equal multiboot2_header } + end + describe '#magic' do subject(:magic) { multiboot2_header.magic } From 962fffbd1844830379ee4e2fcc02b462067f57cc Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:20:40 +0400 Subject: [PATCH 24/40] Add method KernAux::Multiboot2::Header#checksum --- bindings/ruby/ext/default/multiboot2.c | 18 ++++++++++++++++++ .../spec/lib/kernaux/multiboot2/header_spec.rb | 7 +++++++ 2 files changed, 25 insertions(+) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 093257eb..742c3135 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -53,6 +53,13 @@ static VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self); */ static VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self); +/** + * Return the checksum field of the Multiboot 2 header. + * + * @return [nil, Integer] + */ +static VALUE rb_KernAux_Multiboot2_Header_checksum(VALUE self); + void init_multiboot2() { // KernAux::Multiboot2 @@ -88,6 +95,8 @@ void init_multiboot2() rb_KernAux_Multiboot2_Header_arch, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "total_size", rb_KernAux_Multiboot2_Header_total_size, 0); + rb_define_method(rb_KernAux_Multiboot2_Header, "checksum", + rb_KernAux_Multiboot2_Header_checksum, 0); } // KernAux::Multiboot2::Header#enough? @@ -139,4 +148,13 @@ VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self) return ULONG2NUM(total_size); } +// KernAux::Multiboot2::Header#checksum +VALUE rb_KernAux_Multiboot2_Header_checksum(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qnil); + KERNAUX_CAST_CONST(unsigned long, checksum, multiboot2_header->checksum); + return ULONG2NUM(checksum); +} + #endif diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 6a2323f7..8005fadc 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -87,5 +87,12 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal 24 } end + + describe '#checksum' do + subject(:checksum) { multiboot2_header.checksum } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 0x17adaf12 } + end end end From e14788ff3720ea01c58146fcdadfc6aa824768ae Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:24:53 +0400 Subject: [PATCH 25/40] Add more specs --- .../lib/kernaux/multiboot2/header_spec.rb | 122 ++++++++++++++++++ 1 file changed, 122 insertions(+) diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 8005fadc..ade15aa5 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -38,12 +38,36 @@ subject(:enough?) { multiboot2_header.enough? } it { is_expected.to equal true } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal true } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal true } + end end describe '#valid?' do subject(:valid?) { multiboot2_header.valid? } it { is_expected.to equal true } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal true } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal true } + end end describe '#enough!' do @@ -51,6 +75,20 @@ specify { expect { enough! }.not_to raise_error } it { is_expected.to equal multiboot2_header } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + specify { expect { enough! }.not_to raise_error } + it { is_expected.to equal multiboot2_header } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + specify { expect { enough! }.not_to raise_error } + it { is_expected.to equal multiboot2_header } + end end describe '#valid!' do @@ -58,6 +96,20 @@ specify { expect { valid! }.not_to raise_error } it { is_expected.to equal multiboot2_header } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + specify { expect { valid! }.not_to raise_error } + it { is_expected.to equal multiboot2_header } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + specify { expect { valid! }.not_to raise_error } + it { is_expected.to equal multiboot2_header } + end end describe '#magic' do @@ -65,6 +117,20 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal described_class::MAGIC } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal described_class::MAGIC } + end end describe '#arch' do @@ -72,6 +138,20 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0 } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 4 } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 0 } + end end describe '#arch_name' do @@ -79,6 +159,20 @@ it { is_expected.to be_instance_of Symbol } it { is_expected.to equal :i386 } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to be_instance_of Symbol } + it { is_expected.to equal :mips32 } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to be_instance_of Symbol } + it { is_expected.to equal :i386 } + end end describe '#total_size' do @@ -86,6 +180,20 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal 24 } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 104 } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 272 } + end end describe '#checksum' do @@ -93,6 +201,20 @@ it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0x17adaf12 } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 0x17adaebe } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to be_instance_of Integer } + it { is_expected.to equal 0x17adae1a } + end end end end From 7254f8f73de6115370620062fb974c1d2d2fe2b6 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:26:14 +0400 Subject: [PATCH 26/40] Remove unnecessary specs --- .../lib/kernaux/multiboot2/header_spec.rb | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index ade15aa5..030102b1 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -73,20 +73,17 @@ describe '#enough!' do subject(:enough!) { multiboot2_header.enough! } - specify { expect { enough! }.not_to raise_error } it { is_expected.to equal multiboot2_header } context 'for the fixture 1' do let(:fixture) { 1 } - specify { expect { enough! }.not_to raise_error } it { is_expected.to equal multiboot2_header } end context 'for the fixture 2' do let(:fixture) { 2 } - specify { expect { enough! }.not_to raise_error } it { is_expected.to equal multiboot2_header } end end @@ -94,20 +91,17 @@ describe '#valid!' do subject(:valid!) { multiboot2_header.valid! } - specify { expect { valid! }.not_to raise_error } it { is_expected.to equal multiboot2_header } context 'for the fixture 1' do let(:fixture) { 1 } - specify { expect { valid! }.not_to raise_error } it { is_expected.to equal multiboot2_header } end context 'for the fixture 2' do let(:fixture) { 2 } - specify { expect { valid! }.not_to raise_error } it { is_expected.to equal multiboot2_header } end end @@ -115,20 +109,17 @@ describe '#magic' do subject(:magic) { multiboot2_header.magic } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } context 'for the fixture 1' do let(:fixture) { 1 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } end context 'for the fixture 2' do let(:fixture) { 2 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal described_class::MAGIC } end end @@ -136,20 +127,17 @@ describe '#arch' do subject(:arch) { multiboot2_header.arch } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0 } context 'for the fixture 1' do let(:fixture) { 1 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 4 } end context 'for the fixture 2' do let(:fixture) { 2 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0 } end end @@ -157,20 +145,17 @@ describe '#arch_name' do subject(:arch_name) { multiboot2_header.arch_name } - it { is_expected.to be_instance_of Symbol } it { is_expected.to equal :i386 } context 'for the fixture 1' do let(:fixture) { 1 } - it { is_expected.to be_instance_of Symbol } it { is_expected.to equal :mips32 } end context 'for the fixture 2' do let(:fixture) { 2 } - it { is_expected.to be_instance_of Symbol } it { is_expected.to equal :i386 } end end @@ -178,20 +163,17 @@ describe '#total_size' do subject(:total_size) { multiboot2_header.total_size } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 24 } context 'for the fixture 1' do let(:fixture) { 1 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 104 } end context 'for the fixture 2' do let(:fixture) { 2 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 272 } end end @@ -199,20 +181,17 @@ describe '#checksum' do subject(:checksum) { multiboot2_header.checksum } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0x17adaf12 } context 'for the fixture 1' do let(:fixture) { 1 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0x17adaebe } end context 'for the fixture 2' do let(:fixture) { 2 } - it { is_expected.to be_instance_of Integer } it { is_expected.to equal 0x17adae1a } end end From 9bf0b83d6dcab97d2dec9e480e216c13f0f9c398 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:27:39 +0400 Subject: [PATCH 27/40] Enable fixtures on CI --- .cirrus.yml | 2 +- .github/workflows/ruby.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index ba5f2662..2b0b4aee 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -56,7 +56,7 @@ ruby_freebsd_task: - sudo make install main_build_script: - ./autogen.sh - - ./configure --enable-debug CFLAGS='-O3' + - ./configure --enable-debug --enable-fixtures CFLAGS='-O3' - make - sudo make install ruby_build_script: diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml index d5a2ca6d..e19eceac 100644 --- a/.github/workflows/ruby.yml +++ b/.github/workflows/ruby.yml @@ -28,7 +28,7 @@ jobs: - name: autogen run: ./autogen.sh - name: configure - run: ./configure ${{matrix.debug}} ${{matrix.packages.configure}} CFLAGS='-O3' + run: ./configure --enable-fixtures ${{matrix.debug}} ${{matrix.packages.configure}} CFLAGS='-O3' - name: make run: make - name: install From bb0f865ba25524f7ec841b60bf5714b6e9ee0019 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 10:34:26 +0400 Subject: [PATCH 28/40] Add more specs --- .../lib/kernaux/multiboot2/header_spec.rb | 135 +++++++++++++++++- 1 file changed, 131 insertions(+), 4 deletions(-) diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 030102b1..9fd6ad9b 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -4,12 +4,11 @@ if KernAux::Version.with_multiboot2? RSpec.describe KernAux::Multiboot2::Header do - subject(:multiboot2_header) { described_class.new fixture_data } + subject(:multiboot2_header) { described_class.new data } + let(:data) { File.read fixture_path } let(:fixture) { 0 } - let(:fixture_data) { File.read fixture_path } - let :fixture_path do File.expand_path( "../../../../../../fixtures/multiboot2_header_example#{fixture}.bin", @@ -30,7 +29,7 @@ end specify do - expect { freeze }.to change(fixture_data, :frozen?).from(false).to(true) + expect { freeze }.to change(data, :frozen?).from(false).to(true) end end @@ -50,6 +49,18 @@ it { is_expected.to equal true } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal false } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal false } + end end describe '#valid?' do @@ -68,6 +79,18 @@ it { is_expected.to equal true } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal false } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal false } + end end describe '#enough!' do @@ -86,6 +109,28 @@ it { is_expected.to equal multiboot2_header } end + + context 'for empty data' do + let(:data) { '' } + + specify do + expect { enough! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + specify do + expect { enough! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end end describe '#valid!' do @@ -104,6 +149,28 @@ it { is_expected.to equal multiboot2_header } end + + context 'for empty data' do + let(:data) { '' } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end end describe '#magic' do @@ -122,6 +189,18 @@ it { is_expected.to equal described_class::MAGIC } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal nil } + end end describe '#arch' do @@ -140,6 +219,18 @@ it { is_expected.to equal 0 } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal nil } + end end describe '#arch_name' do @@ -158,6 +249,18 @@ it { is_expected.to equal :i386 } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal nil } + end end describe '#total_size' do @@ -176,6 +279,18 @@ it { is_expected.to equal 272 } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal nil } + end end describe '#checksum' do @@ -194,6 +309,18 @@ it { is_expected.to equal 0x17adae1a } end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal nil } + end end end end From c30f3a1fb0a4849663244b1e658a2d9084178bde Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 11:04:31 +0400 Subject: [PATCH 29/40] Validate the expected size --- bindings/ruby/ext/default/multiboot2.c | 19 +++--- .../lib/kernaux/multiboot2/header_spec.rb | 68 +++++++++++++++++++ 2 files changed, 78 insertions(+), 9 deletions(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 742c3135..4316c6a7 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -8,15 +8,15 @@ #define RBNS(s) rb_KernAux_Multiboot2_##s #define EXTRACT_BASE_PTR(Type, name, data, Qnegresult) \ - const struct KernAux_Multiboot2_##Type *const name = \ - (const struct KernAux_Multiboot2_##Type*) \ - StringValuePtr(data); \ - do { \ - const long len = RSTRING_LEN(data); \ - if (len < 0) return (Qnegresult); \ - if ((size_t)len < sizeof(struct KernAux_Multiboot2_##Type)) { \ - return (Qnegresult); \ - } \ + const struct KernAux_Multiboot2_##Type *const name = \ + (const struct KernAux_Multiboot2_##Type*) \ + StringValuePtr(data); \ + const long data_size = RSTRING_LEN(data); \ + do { \ + if (data_size < 0) return (Qnegresult); \ + if ((size_t)data_size < sizeof(struct KernAux_Multiboot2_##Type)) { \ + return (Qnegresult); \ + } \ } while (0) VALUE RBNSMDL = Qnil; // KernAux::Multiboot2 @@ -113,6 +113,7 @@ VALUE rb_KernAux_Multiboot2_Header_validQN(VALUE self) { VALUE data = rb_ivar_get(self, rb_intern("@data")); EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qfalse); + if ((size_t)data_size < multiboot2_header->total_size) return Qfalse; if (KernAux_Multiboot2_Header_is_valid(multiboot2_header)) { return Qtrue; } else { diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 9fd6ad9b..6a78afbd 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -91,6 +91,24 @@ it { is_expected.to equal false } end + + context 'when given size is greater than the expected size' do + let(:data) { "#{[header(0, 24), tag_none].join}\x00" } + + it { is_expected.to equal true } + end + + context 'when given size is equal to the expected size' do + let(:data) { [header(0, 24), tag_none].join } + + it { is_expected.to equal true } + end + + context 'when given size is lesser than the expected size' do + let(:data) { [header(0, 24), tag_none].join[0...-1] } + + it { is_expected.to equal false } + end end describe '#enough!' do @@ -171,6 +189,29 @@ ) end end + + context 'when given size is greater than the expected size' do + let(:data) { "#{[header(0, 24), tag_none].join}\x00" } + + it { is_expected.to equal multiboot2_header } + end + + context 'when given size is equal to the expected size' do + let(:data) { [header(0, 24), tag_none].join } + + it { is_expected.to equal multiboot2_header } + end + + context 'when given size is lesser than the expected size' do + let(:data) { [header(0, 24), tag_none].join[0...-1] } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::InvalidError, + 'The structure is invalid', + ) + end + end end describe '#magic' do @@ -322,5 +363,32 @@ it { is_expected.to equal nil } end end + + def header(arch, total_size) + arch = Integer arch + total_size = Integer total_size + + [ + # uint32_t magic + [described_class::MAGIC].pack('I'), + # uint32_t arch: i386 + [arch].pack('I'), + # uint32_t total_size + [total_size].pack('I'), + # uint32_t checksum + [-(described_class::MAGIC + arch + total_size)].pack('I'), + ].join + end + + def tag_none + [ + # uint16_t tags[0].type: none + [0].pack('S'), + # uint16_t tags[0].flags + [0].pack('S'), + # uint32_t tags[0].size + [8].pack('I'), + ].join + end end end From 6de6e6901377ac41378ea684982d719d1cd07711 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 11:08:42 +0400 Subject: [PATCH 30/40] Improve code --- bindings/ruby/ext/default/multiboot2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 4316c6a7..59602d78 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -19,6 +19,10 @@ } \ } while (0) +#define ENSURE_WHOLE_SIZE(name, Qnegresult) do { \ + if ((size_t)data_size < (name)->total_size) return (Qnegresult); \ +} while (0) + VALUE RBNSMDL = Qnil; // KernAux::Multiboot2 VALUE RBNS(BaseSizeError) = Qnil; // KernAux::Multiboot2::BaseSizeError VALUE RBNS(InvalidError) = Qnil; // KernAux::Multiboot2::InvalidError @@ -113,7 +117,8 @@ VALUE rb_KernAux_Multiboot2_Header_validQN(VALUE self) { VALUE data = rb_ivar_get(self, rb_intern("@data")); EXTRACT_BASE_PTR(Header, multiboot2_header, data, Qfalse); - if ((size_t)data_size < multiboot2_header->total_size) return Qfalse; + ENSURE_WHOLE_SIZE(multiboot2_header, Qfalse); + if (KernAux_Multiboot2_Header_is_valid(multiboot2_header)) { return Qtrue; } else { From 3d6348f92716c9fa89d35ea5bac14ab41e0b2084 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 11:27:00 +0400 Subject: [PATCH 31/40] Add class KernAux::Multiboot2::Info --- bindings/ruby/ext/default/multiboot2.c | 106 +++++++ bindings/ruby/lib/kernaux/multiboot2.rb | 8 + .../spec/lib/kernaux/multiboot2/info_spec.rb | 297 ++++++++++++++++++ 3 files changed, 411 insertions(+) create mode 100644 bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 59602d78..08cee116 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -28,6 +28,13 @@ VALUE RBNS(BaseSizeError) = Qnil; // KernAux::Multiboot2::BaseSizeError VALUE RBNS(InvalidError) = Qnil; // KernAux::Multiboot2::InvalidError VALUE RBNS(Struct) = Qnil; // KernAux::Multiboot2::Struct VALUE RBNS(Header) = Qnil; // KernAux::Multiboot2::Header +VALUE RBNS(Info) = Qnil; // KernAux::Multiboot2::Info + + + +/******************************* + * KernAux::Multiboot2::Header * + *******************************/ static VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self); static VALUE rb_KernAux_Multiboot2_Header_validQN(VALUE self); @@ -53,6 +60,8 @@ static VALUE rb_KernAux_Multiboot2_Header_arch(VALUE self); /** * Return the total size (length) field of the Multiboot 2 header. * + * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + * * @return [nil, Integer] */ static VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self); @@ -60,10 +69,43 @@ static VALUE rb_KernAux_Multiboot2_Header_total_size(VALUE self); /** * Return the checksum field of the Multiboot 2 header. * + * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Header-magic-fields + * * @return [nil, Integer] */ static VALUE rb_KernAux_Multiboot2_Header_checksum(VALUE self); +/***************************** + * KernAux::Multiboot2::Info * + *****************************/ + +static VALUE rb_KernAux_Multiboot2_Info_enoughQN(VALUE self); +static VALUE rb_KernAux_Multiboot2_Info_validQN(VALUE self); + +/** + * Return the total size field of the Multiboot 2 information. + * + * @return [nil, Integer] + * + * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-tags-structure + */ +static VALUE rb_KernAux_Multiboot2_Info_total_size(VALUE self); + +/** + * Return the reserved field of the Multiboot 2 information. + * + * @return [nil, Integer] + * + * @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-tags-structure + */ +static VALUE rb_KernAux_Multiboot2_Info_reserved(VALUE self); + + + +/************************* + * Extension initializer * + *************************/ + void init_multiboot2() { // KernAux::Multiboot2 @@ -101,8 +143,27 @@ void init_multiboot2() rb_KernAux_Multiboot2_Header_total_size, 0); rb_define_method(rb_KernAux_Multiboot2_Header, "checksum", rb_KernAux_Multiboot2_Header_checksum, 0); + + // KernAux::Multiboot2::Info + rb_gc_register_mark_object(rb_KernAux_Multiboot2_Info = + rb_define_class_under( + rb_KernAux_Multiboot2, "Info", rb_KernAux_Multiboot2_Struct)); + rb_define_method(rb_KernAux_Multiboot2_Info, "enough?", + rb_KernAux_Multiboot2_Info_enoughQN, 0); + rb_define_method(rb_KernAux_Multiboot2_Info, "valid?", + rb_KernAux_Multiboot2_Info_validQN, 0); + rb_define_method(rb_KernAux_Multiboot2_Info, "total_size", + rb_KernAux_Multiboot2_Info_total_size, 0); + rb_define_method(rb_KernAux_Multiboot2_Info, "reserved", + rb_KernAux_Multiboot2_Info_reserved, 0); } + + +/******************************* + * KernAux::Multiboot2::Header * + *******************************/ + // KernAux::Multiboot2::Header#enough? VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self) { @@ -163,4 +224,49 @@ VALUE rb_KernAux_Multiboot2_Header_checksum(VALUE self) return ULONG2NUM(checksum); } +/***************************** + * KernAux::Multiboot2::Info * + *****************************/ + +// KernAux::Multiboot2::Info#enough? +VALUE rb_KernAux_Multiboot2_Info_enoughQN(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Info, multiboot2_info, data, Qfalse); + (void)multiboot2_info; // unused + return Qtrue; +} + +// KernAux::Multiboot2::Info#valid? +VALUE rb_KernAux_Multiboot2_Info_validQN(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Info, multiboot2_info, data, Qfalse); + ENSURE_WHOLE_SIZE(multiboot2_info, Qfalse); + + if (KernAux_Multiboot2_Info_is_valid(multiboot2_info)) { + return Qtrue; + } else { + return Qfalse; + } +} + +// KernAux::Multiboot2::Info#total_size +VALUE rb_KernAux_Multiboot2_Info_total_size(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Info, multiboot2_info, data, Qnil); + KERNAUX_CAST_CONST(unsigned long, total_size, multiboot2_info->total_size); + return ULONG2NUM(total_size); +} + +// KernAux::Multiboot2::Info#reserved +VALUE rb_KernAux_Multiboot2_Info_reserved(VALUE self) +{ + VALUE data = rb_ivar_get(self, rb_intern("@data")); + EXTRACT_BASE_PTR(Info, multiboot2_info, data, Qnil); + KERNAUX_CAST_CONST(unsigned long, reserved, multiboot2_info->reserved); + return ULONG2NUM(reserved); +} + #endif diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 0bc23bdc..d706a723 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -100,5 +100,13 @@ class Header < Struct # def arch_name = ARCH[arch] end + + ## + # Multiboot 2 information. + # + # @see https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html#Basic-tags-structure + # + class Info < Struct + end end end diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb new file mode 100644 index 00000000..6c26e7df --- /dev/null +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb @@ -0,0 +1,297 @@ +# frozen_string_literal: true + +require 'spec_helper' + +if KernAux::Version.with_multiboot2? + RSpec.describe KernAux::Multiboot2::Info do + subject(:multiboot2_info) { described_class.new data } + + let(:data) { File.read fixture_path } + let(:fixture) { 0 } + + let :fixture_path do + File.expand_path( + "../../../../../../fixtures/multiboot2_info_example#{fixture}.bin", + __dir__, + ) + end + + describe '#freeze' do + subject(:freeze) { multiboot2_info.freeze } + + it { is_expected.to equal multiboot2_info } + + specify do + expect { freeze }.to \ + change(multiboot2_info, :frozen?) + .from(false) + .to(true) + end + + specify do + expect { freeze }.to change(data, :frozen?).from(false).to(true) + end + end + + describe '#enough?' do + subject(:enough?) { multiboot2_info.enough? } + + it { is_expected.to equal true } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal true } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal true } + end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal false } + end + + context 'for too small data' do + let(:data) { "\x00" * 7 } + + it { is_expected.to equal false } + end + end + + describe '#valid?' do + subject(:valid?) { multiboot2_info.valid? } + + it { is_expected.to equal true } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal true } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal true } + end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal false } + end + + context 'for too small data' do + let(:data) { "\x00" * 15 } + + it { is_expected.to equal false } + end + + context 'when given size is greater than the expected size' do + let(:data) { "#{[info(16), tag_none].join}\x00" } + + it { is_expected.to equal true } + end + + context 'when given size is equal to the expected size' do + let(:data) { [info(16), tag_none].join } + + it { is_expected.to equal true } + end + + context 'when given size is lesser than the expected size' do + let(:data) { [info(16), tag_none].join[0...-1] } + + it { is_expected.to equal false } + end + end + + describe '#enough!' do + subject(:enough!) { multiboot2_info.enough! } + + it { is_expected.to equal multiboot2_info } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal multiboot2_info } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal multiboot2_info } + end + + context 'for empty data' do + let(:data) { '' } + + specify do + expect { enough! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'for too small data' do + let(:data) { "\x00" * 7 } + + specify do + expect { enough! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + end + + describe '#valid!' do + subject(:valid!) { multiboot2_info.valid! } + + it { is_expected.to equal multiboot2_info } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal multiboot2_info } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal multiboot2_info } + end + + context 'for empty data' do + let(:data) { '' } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'for too small data' do + let(:data) { "\x00" * 7 } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'when given size is greater than the expected size' do + let(:data) { "#{[info(16), tag_none].join}\x00" } + + it { is_expected.to equal multiboot2_info } + end + + context 'when given size is equal to the expected size' do + let(:data) { [info(16), tag_none].join } + + it { is_expected.to equal multiboot2_info } + end + + context 'when given size is lesser than the expected size' do + let(:data) { [info(16), tag_none].join[0...-1] } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::InvalidError, + 'The structure is invalid', + ) + end + end + end + + describe '#total_size' do + subject(:total_size) { multiboot2_info.total_size } + + it { is_expected.to equal 16 } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal 864 } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal 1816 } + end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 7 } + + it { is_expected.to equal nil } + end + end + + describe '#reserved' do + subject(:reserved) { multiboot2_info.reserved } + + it { is_expected.to equal 0 } + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal 0 } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal 0 } + end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal nil } + end + + context 'for too small data' do + let(:data) { "\x00" * 7 } + + it { is_expected.to equal nil } + end + end + + def info(total_size) + total_size = Integer total_size + + [ + # uint32_t total_size + [total_size].pack('I'), + # uint32_t reserved + [0].pack('I'), + ].join + end + + def tag_none + [ + # uint32_t tags[0].type: none + [0].pack('I'), + # uint32_t tags[0].size + [8].pack('I'), + ].join + end + end +end From d8ceac67cb53c50859769595ad7cc5fe050ed0d8 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 11:39:26 +0400 Subject: [PATCH 32/40] Fix docs --- bindings/ruby/ext/default/multiboot2.c | 22 ++++++++++++++++++++++ bindings/ruby/lib/kernaux/multiboot2.rb | 22 ++++++++++++++++++++-- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/bindings/ruby/ext/default/multiboot2.c b/bindings/ruby/ext/default/multiboot2.c index 08cee116..011b7f21 100644 --- a/bindings/ruby/ext/default/multiboot2.c +++ b/bindings/ruby/ext/default/multiboot2.c @@ -36,7 +36,18 @@ VALUE RBNS(Info) = Qnil; // KernAux::Multiboot2::Info * KernAux::Multiboot2::Header * *******************************/ +/** + * Test whether a Multiboot 2 header data is not shorter than it's base. + * + * @return [Boolean] + */ static VALUE rb_KernAux_Multiboot2_Header_enoughQN(VALUE self); + +/** + * Test whether a Multiboot 2 header is valid. + * + * @return [Boolean] + */ static VALUE rb_KernAux_Multiboot2_Header_validQN(VALUE self); /** @@ -79,7 +90,18 @@ static VALUE rb_KernAux_Multiboot2_Header_checksum(VALUE self); * KernAux::Multiboot2::Info * *****************************/ +/** + * Test whether a Multiboot 2 information data is not shorter than it's base. + * + * @return [Boolean] + */ static VALUE rb_KernAux_Multiboot2_Info_enoughQN(VALUE self); + +/** + * Test whether a Multiboot 2 information is valid. + * + * @return [Boolean] + */ static VALUE rb_KernAux_Multiboot2_Info_validQN(VALUE self); /** diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index d706a723..6003a83b 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -8,8 +8,8 @@ module KernAux # module Multiboot2 ## - # Raised when a Multiboot 2 structure which is shorter than even it's base - # requested to be enough sized. + # Raised when a Multiboot 2 structure data which is shorter + # than even it's base requested to be enough sized. # # @see Struct#enough! # @@ -40,15 +40,31 @@ def freeze self end + # :nocov: + + ## + # Test whether a Multiboot 2 structure data is not shorter than it's base. + # + # @return [Boolean] + # def enough? raise NotImplementedError, "#{self.class}#enough?" end + ## + # Test whether a Multiboot 2 structure is valid. + # + # @return [Boolean] + # def valid? raise NotImplementedError, "#{self.class}#valid?" end + # :nocov: + ## + # @return [Struct] self + # # @raise [BaseSizeError] the structure size is too small # def enough! @@ -58,6 +74,8 @@ def enough! end ## + # @return [Struct] self + # # @raise [BaseSizeError] the structure size is too small # @raise [InvalidError] the structure is invalid # From f350f68a750c26d19a60073250fe260a815e56d9 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 11:44:58 +0400 Subject: [PATCH 33/40] Upgrade gems --- bindings/mruby/Gemfile | 6 +++--- bindings/ruby/kernaux.gemspec | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bindings/mruby/Gemfile b/bindings/mruby/Gemfile index 50f4deb6..0c1c099f 100644 --- a/bindings/mruby/Gemfile +++ b/bindings/mruby/Gemfile @@ -2,8 +2,8 @@ source 'https://rubygems.org' -gem 'bundler', '~> 2.2' +gem 'bundler', '~> 2.3' gem 'rake', '~> 13.0' -gem 'rubocop', '~> 1.25' -gem 'rubocop-performance', '~> 1.13' +gem 'rubocop', '~> 1.40' +gem 'rubocop-performance', '~> 1.15' gem 'rubocop-rake', '~> 0.6' diff --git a/bindings/ruby/kernaux.gemspec b/bindings/ruby/kernaux.gemspec index 1dec6634..57d7d577 100644 --- a/bindings/ruby/kernaux.gemspec +++ b/bindings/ruby/kernaux.gemspec @@ -45,15 +45,15 @@ Gem::Specification.new do |spec| spec.extensions << 'ext/default/extconf.rb' - spec.add_development_dependency 'bundler', '~> 2.2' + spec.add_development_dependency 'bundler', '~> 2.3' spec.add_development_dependency 'pry', '~> 0.14' spec.add_development_dependency 'rake', '~> 13.0' - spec.add_development_dependency 'rake-compiler', '~> 1.1' - spec.add_development_dependency 'rspec', '~> 3.10' - spec.add_development_dependency 'rubocop', '~> 1.25' - spec.add_development_dependency 'rubocop-performance', '~> 1.13' + spec.add_development_dependency 'rake-compiler', '~> 1.2' + spec.add_development_dependency 'rspec', '~> 3.12' + spec.add_development_dependency 'rubocop', '~> 1.40' + spec.add_development_dependency 'rubocop-performance', '~> 1.15' spec.add_development_dependency 'rubocop-rake', '~> 0.6' - spec.add_development_dependency 'rubocop-rspec', '~> 2.7' + spec.add_development_dependency 'rubocop-rspec', '~> 2.16' spec.add_development_dependency 'simplecov', '~> 0.21' spec.add_development_dependency 'yard', '~> 0.9' end From 5d9de034be3c0d3bd6dc4ac468a67505e0a7c30b Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 12:06:33 +0400 Subject: [PATCH 34/40] Add a shared example --- .../lib/kernaux/multiboot2/header_spec.rb | 149 +------------- .../spec/lib/kernaux/multiboot2/info_spec.rb | 149 +------------- .../spec/shared_examples/multiboot2_struct.rb | 191 ++++++++++++++++++ bindings/ruby/spec/spec_helper.rb | 2 + 4 files changed, 195 insertions(+), 296 deletions(-) create mode 100644 bindings/ruby/spec/shared_examples/multiboot2_struct.rb diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb index 6a78afbd..29510a3d 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/header_spec.rb @@ -16,82 +16,11 @@ ) end - describe '#freeze' do - subject(:freeze) { multiboot2_header.freeze } - - it { is_expected.to equal multiboot2_header } - - specify do - expect { freeze }.to \ - change(multiboot2_header, :frozen?) - .from(false) - .to(true) - end - - specify do - expect { freeze }.to change(data, :frozen?).from(false).to(true) - end - end - - describe '#enough?' do - subject(:enough?) { multiboot2_header.enough? } - - it { is_expected.to equal true } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal true } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal true } - end - - context 'for empty data' do - let(:data) { '' } - - it { is_expected.to equal false } - end - - context 'for too small data' do - let(:data) { "\x00" * 15 } - - it { is_expected.to equal false } - end - end + it_behaves_like 'Multiboot 2 struct', :header, 16 describe '#valid?' do subject(:valid?) { multiboot2_header.valid? } - it { is_expected.to equal true } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal true } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal true } - end - - context 'for empty data' do - let(:data) { '' } - - it { is_expected.to equal false } - end - - context 'for too small data' do - let(:data) { "\x00" * 15 } - - it { is_expected.to equal false } - end - context 'when given size is greater than the expected size' do let(:data) { "#{[header(0, 24), tag_none].join}\x00" } @@ -111,85 +40,9 @@ end end - describe '#enough!' do - subject(:enough!) { multiboot2_header.enough! } - - it { is_expected.to equal multiboot2_header } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal multiboot2_header } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal multiboot2_header } - end - - context 'for empty data' do - let(:data) { '' } - - specify do - expect { enough! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - - context 'for too small data' do - let(:data) { "\x00" * 15 } - - specify do - expect { enough! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - end - describe '#valid!' do subject(:valid!) { multiboot2_header.valid! } - it { is_expected.to equal multiboot2_header } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal multiboot2_header } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal multiboot2_header } - end - - context 'for empty data' do - let(:data) { '' } - - specify do - expect { valid! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - - context 'for too small data' do - let(:data) { "\x00" * 15 } - - specify do - expect { valid! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - context 'when given size is greater than the expected size' do let(:data) { "#{[header(0, 24), tag_none].join}\x00" } diff --git a/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb b/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb index 6c26e7df..aaf252a3 100644 --- a/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb +++ b/bindings/ruby/spec/lib/kernaux/multiboot2/info_spec.rb @@ -16,82 +16,11 @@ ) end - describe '#freeze' do - subject(:freeze) { multiboot2_info.freeze } - - it { is_expected.to equal multiboot2_info } - - specify do - expect { freeze }.to \ - change(multiboot2_info, :frozen?) - .from(false) - .to(true) - end - - specify do - expect { freeze }.to change(data, :frozen?).from(false).to(true) - end - end - - describe '#enough?' do - subject(:enough?) { multiboot2_info.enough? } - - it { is_expected.to equal true } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal true } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal true } - end - - context 'for empty data' do - let(:data) { '' } - - it { is_expected.to equal false } - end - - context 'for too small data' do - let(:data) { "\x00" * 7 } - - it { is_expected.to equal false } - end - end + it_behaves_like 'Multiboot 2 struct', :info, 8 describe '#valid?' do subject(:valid?) { multiboot2_info.valid? } - it { is_expected.to equal true } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal true } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal true } - end - - context 'for empty data' do - let(:data) { '' } - - it { is_expected.to equal false } - end - - context 'for too small data' do - let(:data) { "\x00" * 15 } - - it { is_expected.to equal false } - end - context 'when given size is greater than the expected size' do let(:data) { "#{[info(16), tag_none].join}\x00" } @@ -111,85 +40,9 @@ end end - describe '#enough!' do - subject(:enough!) { multiboot2_info.enough! } - - it { is_expected.to equal multiboot2_info } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal multiboot2_info } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal multiboot2_info } - end - - context 'for empty data' do - let(:data) { '' } - - specify do - expect { enough! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - - context 'for too small data' do - let(:data) { "\x00" * 7 } - - specify do - expect { enough! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - end - describe '#valid!' do subject(:valid!) { multiboot2_info.valid! } - it { is_expected.to equal multiboot2_info } - - context 'for the fixture 1' do - let(:fixture) { 1 } - - it { is_expected.to equal multiboot2_info } - end - - context 'for the fixture 2' do - let(:fixture) { 2 } - - it { is_expected.to equal multiboot2_info } - end - - context 'for empty data' do - let(:data) { '' } - - specify do - expect { valid! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - - context 'for too small data' do - let(:data) { "\x00" * 7 } - - specify do - expect { valid! }.to raise_error( - KernAux::Multiboot2::BaseSizeError, - 'The structure size is too small', - ) - end - end - context 'when given size is greater than the expected size' do let(:data) { "#{[info(16), tag_none].join}\x00" } diff --git a/bindings/ruby/spec/shared_examples/multiboot2_struct.rb b/bindings/ruby/spec/shared_examples/multiboot2_struct.rb new file mode 100644 index 00000000..52aa138a --- /dev/null +++ b/bindings/ruby/spec/shared_examples/multiboot2_struct.rb @@ -0,0 +1,191 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'Multiboot 2 struct' do |struct_name, min_size| + struct_name = String(struct_name).to_sym + min_size = Integer min_size + + subject(:multiboot2_struct) { described_class.new data } + + let(:data) { File.read fixture_path } + let(:fixture) { 0 } + + let :fixture_path do + File.expand_path( + "../../../../fixtures/multiboot2_#{struct_name}_example#{fixture}.bin", + __dir__, + ) + end + + describe '#freeze' do + subject(:freeze) { multiboot2_struct.freeze } + + it { is_expected.to equal multiboot2_struct } + + specify do + expect { freeze }.to \ + change(multiboot2_struct, :frozen?) + .from(false) + .to(true) + end + + specify do + expect { freeze }.to change(data, :frozen?).from(false).to(true) + end + end + + describe '#enough?' do + subject(:enough?) { multiboot2_struct.enough? } + + context 'for the fixture 0' do + let(:fixture) { 0 } + + it { is_expected.to equal true } + end + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal true } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal true } + end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal false } + end + + context 'for too small data' do + let(:data) { "\x00" * (min_size - 1) } + + it { is_expected.to equal false } + end + end + + describe '#valid?' do + subject(:valid?) { multiboot2_struct.valid? } + + context 'for the fixture 0' do + let(:fixture) { 0 } + + it { is_expected.to equal true } + end + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal true } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal true } + end + + context 'for empty data' do + let(:data) { '' } + + it { is_expected.to equal false } + end + + context 'for too small data' do + let(:data) { "\x00" * (min_size - 1) } + + it { is_expected.to equal false } + end + end + + describe '#enough!' do + subject(:enough!) { multiboot2_struct.enough! } + + context 'for the fixture 0' do + let(:fixture) { 0 } + + it { is_expected.to equal multiboot2_struct } + end + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal multiboot2_struct } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal multiboot2_struct } + end + + context 'for empty data' do + let(:data) { '' } + + specify do + expect { enough! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'for too small data' do + let(:data) { "\x00" * (min_size - 1) } + + specify do + expect { enough! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + end + + describe '#valid!' do + subject(:valid!) { multiboot2_struct.valid! } + + context 'for the fixture 0' do + let(:fixture) { 0 } + + it { is_expected.to equal multiboot2_struct } + end + + context 'for the fixture 1' do + let(:fixture) { 1 } + + it { is_expected.to equal multiboot2_struct } + end + + context 'for the fixture 2' do + let(:fixture) { 2 } + + it { is_expected.to equal multiboot2_struct } + end + + context 'for empty data' do + let(:data) { '' } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + + context 'for too small data' do + let(:data) { "\x00" * (min_size - 1) } + + specify do + expect { valid! }.to raise_error( + KernAux::Multiboot2::BaseSizeError, + 'The structure size is too small', + ) + end + end + end +end diff --git a/bindings/ruby/spec/spec_helper.rb b/bindings/ruby/spec/spec_helper.rb index 7d7af858..f707405e 100644 --- a/bindings/ruby/spec/spec_helper.rb +++ b/bindings/ruby/spec/spec_helper.rb @@ -23,6 +23,8 @@ require 'yaml' +Dir[File.expand_path('shared_examples/*.rb', __dir__)].each { |f| require f } + RSpec.configure do |config| # rspec-expectations config goes here. You can use an alternate # assertion/expectation library such as wrong or the stdlib/minitest From b5837016e8751ccea371f622278bd6ce96866a9c Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 12:27:06 +0400 Subject: [PATCH 35/40] Add method KernAux::Multiboot2::Struct#inspect --- bindings/ruby/lib/kernaux/multiboot2.rb | 12 ++++++ .../spec/shared_examples/multiboot2_struct.rb | 38 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 6003a83b..f826e7fe 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -31,6 +31,18 @@ def initialize(data = '') freeze if @data.frozen? end + ## + # @return [String] + # + def inspect + '#<' \ + "#{self.class}" \ + ':' \ + "#{@data[...16].force_encoding(Encoding::ASCII).inspect}" \ + "#{'...' if @data.size > 16}" \ + '>'.freeze + end + ## # Freeze the structure and it's underlying data. # diff --git a/bindings/ruby/spec/shared_examples/multiboot2_struct.rb b/bindings/ruby/spec/shared_examples/multiboot2_struct.rb index 52aa138a..f24877ba 100644 --- a/bindings/ruby/spec/shared_examples/multiboot2_struct.rb +++ b/bindings/ruby/spec/shared_examples/multiboot2_struct.rb @@ -16,6 +16,44 @@ ) end + describe '#inspect' do + subject(:inspect) { multiboot2_struct.inspect } + + context 'when data is empty' do + let(:data) { '' } + + it { is_expected.to be_instance_of String } + it { is_expected.to be_frozen } + it { is_expected.to eq "#<#{described_class}:\"\">" } + end + + context 'when data is not too long' do + let(:data) { "\x00" * 16 } + + it { is_expected.to be_instance_of String } + it { is_expected.to be_frozen } + + specify do + expect(inspect).to eq \ + "#<#{described_class}:" \ + "#{data.force_encoding(Encoding::ASCII).inspect}>" + end + end + + context 'when data is too long' do + let(:data) { "\x00" * 17 } + + it { is_expected.to be_instance_of String } + it { is_expected.to be_frozen } + + specify do + expect(inspect).to eq \ + "#<#{described_class}:" \ + "#{data[...16].force_encoding(Encoding::ASCII).inspect}...>" + end + end + end + describe '#freeze' do subject(:freeze) { multiboot2_struct.freeze } From 82aff9492cc179b12c8bff91c4c513307c228ba6 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 12:39:45 +0400 Subject: [PATCH 36/40] Fix FreeBSD build --- bindings/mruby/Gemfile | 2 +- bindings/ruby/kernaux.gemspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/mruby/Gemfile b/bindings/mruby/Gemfile index 0c1c099f..b8c2348f 100644 --- a/bindings/mruby/Gemfile +++ b/bindings/mruby/Gemfile @@ -2,7 +2,7 @@ source 'https://rubygems.org' -gem 'bundler', '~> 2.3' +gem 'bundler', '~> 2.2' gem 'rake', '~> 13.0' gem 'rubocop', '~> 1.40' gem 'rubocop-performance', '~> 1.15' diff --git a/bindings/ruby/kernaux.gemspec b/bindings/ruby/kernaux.gemspec index 57d7d577..a88d8e64 100644 --- a/bindings/ruby/kernaux.gemspec +++ b/bindings/ruby/kernaux.gemspec @@ -45,7 +45,7 @@ Gem::Specification.new do |spec| spec.extensions << 'ext/default/extconf.rb' - spec.add_development_dependency 'bundler', '~> 2.3' + spec.add_development_dependency 'bundler', '~> 2.2' spec.add_development_dependency 'pry', '~> 0.14' spec.add_development_dependency 'rake', '~> 13.0' spec.add_development_dependency 'rake-compiler', '~> 1.2' From e1fe88be2069d71d147a84f82a39c08cbd00b804 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 18 Dec 2022 13:08:39 +0400 Subject: [PATCH 37/40] Edit docs --- README.md | 2 +- bindings/ruby/lib/kernaux/multiboot2.rb | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 833b7618..0abe55ff 100644 --- a/README.md +++ b/README.md @@ -42,9 +42,9 @@ zero). Work-in-progress APIs can change at any time. * [Feature macros](/include/kernaux/version.h.in) (*work in progress*) * [Macros](/include/kernaux/macro.h) (*non-breaking since* **0.6.0**) * [Example: packing](/examples/macro_packing.c) + * [Example: BITS](/examples/macro_bits.c) * [Example: CAST\_\*](/examples/macro_cast.c); * [Example: CONTAINER\_OF](/examples/macro_container_of.c) - * [Example: BITS](/examples/macro_bits.c) * [Example: STATIC\_TEST\*](/examples/macro_static_test.c) * [Assertions](/include/kernaux/assert.h) (*non-breaking since* **0.4.0**) * [Example: Assert](/examples/assert.c) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index f826e7fe..72bc75e5 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -23,7 +23,9 @@ class BaseSizeError < Error; end class InvalidError < Error; end ## - # The base class for any Multiboot 2 structure. + # The base class for Multiboot 2 {Header} and {Info}. + # + # @abstract It requires an implementation in C to use **libkernaux**. # class Struct def initialize(data = '') @@ -57,6 +59,7 @@ def freeze ## # Test whether a Multiboot 2 structure data is not shorter than it's base. # + # @abstract # @return [Boolean] # def enough? @@ -66,6 +69,7 @@ def enough? ## # Test whether a Multiboot 2 structure is valid. # + # @abstract # @return [Boolean] # def valid? From 3e1fd1e614f7e672db7b3bfbe34ac9112949dd02 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Mon, 19 Dec 2022 13:18:26 +0400 Subject: [PATCH 38/40] Add methods KernAux::Multiboot2::Struct#data, #to_s --- bindings/ruby/lib/kernaux/multiboot2.rb | 7 +++++++ .../spec/shared_examples/multiboot2_struct.rb | 16 ++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 72bc75e5..9df9a8b0 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -28,11 +28,18 @@ class InvalidError < Error; end # @abstract It requires an implementation in C to use **libkernaux**. # class Struct + ## + # @return [String] + # + attr_reader :data + def initialize(data = '') @data = String data freeze if @data.frozen? end + alias to_s data + ## # @return [String] # diff --git a/bindings/ruby/spec/shared_examples/multiboot2_struct.rb b/bindings/ruby/spec/shared_examples/multiboot2_struct.rb index f24877ba..b3008a29 100644 --- a/bindings/ruby/spec/shared_examples/multiboot2_struct.rb +++ b/bindings/ruby/spec/shared_examples/multiboot2_struct.rb @@ -16,6 +16,18 @@ ) end + describe '#data' do + subject { multiboot2_struct.data } + + it { is_expected.to equal data } + end + + describe '#to_s' do + subject { multiboot2_struct.to_s } + + it { is_expected.to equal data } + end + describe '#inspect' do subject(:inspect) { multiboot2_struct.inspect } @@ -72,7 +84,7 @@ end describe '#enough?' do - subject(:enough?) { multiboot2_struct.enough? } + subject { multiboot2_struct.enough? } context 'for the fixture 0' do let(:fixture) { 0 } @@ -106,7 +118,7 @@ end describe '#valid?' do - subject(:valid?) { multiboot2_struct.valid? } + subject { multiboot2_struct.valid? } context 'for the fixture 0' do let(:fixture) { 0 } From 16978c545ad47e032d5462604685b4f26238b3f9 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Mon, 19 Dec 2022 13:21:31 +0400 Subject: [PATCH 39/40] Remove unnecessary code --- bindings/ruby/lib/kernaux/multiboot2.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/ruby/lib/kernaux/multiboot2.rb b/bindings/ruby/lib/kernaux/multiboot2.rb index 9df9a8b0..64dc0412 100644 --- a/bindings/ruby/lib/kernaux/multiboot2.rb +++ b/bindings/ruby/lib/kernaux/multiboot2.rb @@ -58,7 +58,6 @@ def inspect def freeze @data.freeze super - self end # :nocov: From 519b70e90d9588f82c56ffd212cacaa718daa5ca Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Fri, 23 Dec 2022 14:39:45 +0400 Subject: [PATCH 40/40] Yank gems and crates --- sha256sums.txt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sha256sums.txt b/sha256sums.txt index 2fc1a693..8abfd286 100644 --- a/sha256sums.txt +++ b/sha256sums.txt @@ -14,15 +14,6 @@ c0bc0ed3c396893797912356366068ad04054ade23e293bbf61c72975165a3fc kernaux-0.5.0. da5fbc5ad8d0d1f3c7a9c8627b59bb9c670893eed800f7b2190c81767f8bb70f kernaux-0.5.0.gem # 893292882e0b658d92e104dc0d2974d61daca60efdf9fdf80996c3db54b0cab2 libkernaux-0.4.0.tar.gz -eb27d72d658f87638998cdb0056018edd49cc8f1144e23a1e00f7921a6bbd5b2 kernaux-0.4.0.crate -ee0d63d1f86113f3f652427b908da27fda7be496b5bdbba9947977891b2e50ef kernaux-sys-0.4.0.crate -2c765894b10830abc5945b003d465515fb28b964f1e2f7cdd5594bbf1cdbce97 kernaux-0.4.0.gem -# 6887939c01b65a4e864d47f103a06a6ad1639f4bffaa5582c95252c4646c8d2a libkernaux-0.3.0.tar.gz -564e5a58a854dd6b2b4e212ebac9c76a099971a2fa95324916de07b67f46934c kernaux-0.3.0.crate -1fddd0383dcce818273f305fffd0c7153d3772fcaf78dae38c30dae4f0960a25 kernaux-sys-0.3.0.crate -986b84827466d4ba7244c2e3ba41502a7984156346613af545946423f913d520 kernaux-0.3.0.gem -# -# Yanked: 00b22e28ecddde5beca8b7d425d91eaf3634ee1d9df0bcf9565938d02353cd49 libkernaux-0.2.0.tar.gz b80c1d94519a43bd92c2b1a7626bdb5af5aa98dd993b2332d56449b0be7dbc8f libkernaux-0.1.0.tar.gz