Permalink
Fetching contributors…
Cannot retrieve contributors at this time
497 lines (394 sloc) 10.6 KB
require 'spec_helper'
require 'ronin/binary/struct'
describe Binary::Struct do
describe "layout" do
subject do
struct = Class.new(described_class)
struct.class_eval do
layout :x, :uint,
:y, :uint
end
struct.new
end
it "should return the layout" do
subject.class.layout.should == [
:x,
:y
]
end
context "when given fields" do
it "should populate fields" do
subject.class.fields.should == {
:x => [:uint, nil],
:y => [:uint, nil]
}
end
it "should define reader methods" do
subject.should respond_to(:x)
subject.should respond_to(:y)
end
it "should define writer methods" do
subject.should respond_to(:x=)
subject.should respond_to(:y=)
end
end
end
describe "field?" do
subject do
struct = Class.new(described_class)
struct.class_eval { layout :x, :uint }
struct
end
it "should determine if fields exist" do
subject.field?(:x).should == true
subject.field?(:foo).should == false
end
end
describe "endian" do
subject do
struct = Class.new(described_class)
struct.class_eval { endian :little }
struct
end
it "should return the endianness of the Struct" do
subject.endian.should == :little
end
context "when given an argument" do
it "should set the endianness" do
subject.endian :big
subject.endian.should == :big
end
end
end
describe "typedefs" do
end
describe "typedef" do
subject do
struct = Class.new(described_class)
struct.class_eval do
typedef :uint32_t, :test_t
end
struct
end
it "should register a new type in typedefs" do
subject.typedefs.should have_key(:test_t)
end
it "should resolve the existing type" do
subject.typedefs[:test_t].should == :uint32
end
end
describe "#initialize" do
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint
end
layout :int, :uint,
:int_array, [:uint, 2],
:float, :float,
:float_array, [:float, 2],
:char, :char,
:char_array, [:char, 2],
:string, :string,
:struct, nested_struct,
:struct_array, [nested_struct, 2]
end
struct.new
end
it "should set integers to 0" do
subject[:int].should == 0
end
it "should set arrays of integers to [0, ...]" do
subject[:int_array].should == [0, 0]
end
it "should set floats to 0.0" do
subject[:float].should == 0.0
end
it "should set arrays of floats to [0.0, ...]" do
subject[:float_array].should == [0.0, 0.0]
end
it "should set chars to '\\0'" do
subject[:char].should == "\0"
end
it "should set arrays of chars to ''" do
subject[:char_array].should == ''
end
it "should set strings to ''" do
subject[:string].should == ''
end
it "should initialize nested structs" do
subject[:struct][:int].should == 0
end
it "should initialize arrays of nested structs" do
subject[:struct_array][0][:int].should == 0
subject[:struct_array][1][:int].should == 0
end
end
describe "#[]" do
subject do
struct = Class.new(described_class)
struct.class_eval do
layout :x, :uint,
:y, :uint
end
struct.new
end
before(:all) do
subject.instance_variable_set('@x',10)
end
it "should access the instance variable" do
subject[:x].should == 10
end
it "should still call the underlying reader method" do
subject.should_receive(:x).and_return(10)
subject[:x]
end
it "should raise ArgumentError for unknown fields" do
lambda {
subject[:foo]
}.should raise_error(ArgumentError)
end
end
describe "#[]=" do
subject do
struct = Class.new(described_class)
struct.class_eval do
layout :x, :uint,
:y, :uint
end
struct.new
end
before(:each) do
subject.instance_variable_set('@x',0)
end
it "should set the underlying instance variable" do
subject[:x] = 20
subject.instance_variable_get('@x').should == 20
end
it "should still call the underlying writer method" do
subject.should_receive(:x=).with(20)
subject[:x] = 20
end
it "should raise ArgumentError for unknown fields" do
lambda {
subject[:foo] = 20
}.should raise_error(ArgumentError)
end
end
describe "#values" do
let(:x) { 10 }
let(:y) { 20 }
subject do
struct = Class.new(described_class)
struct.class_eval do
layout :x, :uint,
:y, :uint
end
struct.new
end
before(:each) do
subject.x = x
subject.y = y
end
it "should return the values of the fields" do
subject.values.should == [x, y]
end
context "nested structs" do
let(:z) { 30 }
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint
end
layout :x, :uint,
:y, :uint,
:z, nested_struct
end
struct.new
end
before(:each) do
subject.z.int = z
end
it "should nest the values of nested structs" do
subject.values.should == [x, y, [z]]
end
end
context "arrays of nested structs" do
let(:z) { 30 }
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint
end
layout :x, :uint,
:y, :uint,
:z, [nested_struct, 2]
end
struct.new
end
before(:each) do
subject.z[0].int = z
subject.z[1].int = z
end
it "should nest the values of nested structs" do
subject.values.should == [x, y, [[z], [z]]]
end
end
end
describe "#clear" do
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :int
end
layout :x, :uint,
:y, :float,
:z, nested_struct
end
struct.new
end
before(:all) do
subject.x = 100
subject.y = 15.0
subject.z.int = -1
subject.clear
end
it "should reset fields to their default values" do
subject.x.should == 0
subject.y.should == 0.0
end
it "should reinitialize nested structs" do
subject.z.int.should == 0
end
end
describe "#pack" do
context "arrays of chars" do
let(:string) { "hello" }
let(:packed) { string.ljust(10,"\0") }
subject do
struct = Class.new(described_class)
struct.class_eval do
layout :chars, [:char, 10]
end
struct.new
end
before(:each) do
subject.chars = string
end
it "should pack arrays of chars into a String" do
subject.pack.should == packed
end
end
context "structs" do
let(:packed) { "\x0a\x00\x14\x00\x00\x00" }
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint32_le
end
layout :int, :uint16_le,
:struct, nested_struct
end
struct.new
end
before(:each) do
subject.int = 10
subject.struct.int = 20
end
it "should pack the nested struct fields" do
subject.pack.should == packed
end
end
context "arrays of structs" do
let(:packed) { "\x0a\x00\x14\x00\x00\x00\x1e\x00\x00\x00" }
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint32_le
end
layout :int, :uint16_le,
:struct, [nested_struct, 2]
end
struct.new
end
before(:each) do
subject.int = 10
subject.struct[0].int = 20
subject.struct[1].int = 30
end
it "should pack the nested fields" do
subject.pack.should == packed
end
end
end
describe "#unpack" do
context "arrays of chars" do
let(:string) { "hello" }
let(:packed) { string.ljust(10,"\0") }
subject do
struct = Class.new(described_class)
struct.class_eval do
layout :chars, [:char, 10]
end
struct.new
end
it "should unpack arrays of chars into a String" do
subject.unpack(packed)
subject.chars.should == string
end
end
context "structs" do
let(:packed) { "\x0a\x00\x14\x00\x00\x00" }
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint32_le
end
layout :int, :uint16_le,
:struct, nested_struct
end
struct.new
end
it "should unpack the nested struct fields" do
subject.unpack(packed)
subject.int.should == 10
subject.struct.int.should == 20
end
end
context "arrays of structs" do
let(:packed) { "\x0a\x00\x14\x00\x00\x00\x1e\x00\x00\x00" }
subject do
struct = Class.new(described_class)
struct.class_eval do
nested_struct = Class.new(Ronin::Binary::Struct)
nested_struct.class_eval do
layout :int, :uint32_le
end
layout :int, :uint16_le,
:struct, [nested_struct, 2]
end
struct.new
end
it "should unpack the nested fields" do
subject.unpack(packed)
subject.int.should == 10
subject.struct[0].int.should == 20
subject.struct[1].int.should == 30
end
end
end
end