cauterize 0.0.1.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.rspec +1 -0
- data/.travisci.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +152 -0
- data/Rakefile +38 -0
- data/bin/cauterize +53 -0
- data/c/src/cauterize.c +74 -0
- data/c/src/cauterize.h +46 -0
- data/c/src/cauterize_debug.h +29 -0
- data/c/src/cauterize_util.h +7 -0
- data/c/test/greatest.h +536 -0
- data/c/test/test.c +166 -0
- data/cauterize.gemspec +26 -0
- data/example/Cauterize +44 -0
- data/example/build.sh +4 -0
- data/lib/cauterize/base_type.rb +96 -0
- data/lib/cauterize/builders.rb +27 -0
- data/lib/cauterize/builders/c/buildable.rb +59 -0
- data/lib/cauterize/builders/c/composite.rb +55 -0
- data/lib/cauterize/builders/c/enumeration.rb +41 -0
- data/lib/cauterize/builders/c/fixed_array.rb +62 -0
- data/lib/cauterize/builders/c/group.rb +95 -0
- data/lib/cauterize/builders/c/scalar.rb +31 -0
- data/lib/cauterize/builders/c/variable_array.rb +90 -0
- data/lib/cauterize/c_builder.rb +63 -0
- data/lib/cauterize/cauterize.rb +33 -0
- data/lib/cauterize/composite.rb +50 -0
- data/lib/cauterize/enumeration.rb +77 -0
- data/lib/cauterize/fixed_array.rb +43 -0
- data/lib/cauterize/formatter.rb +59 -0
- data/lib/cauterize/group.rb +56 -0
- data/lib/cauterize/scalar.rb +38 -0
- data/lib/cauterize/snake_case.rb +21 -0
- data/lib/cauterize/variable_array.rb +56 -0
- data/lib/cauterize/version.rb +3 -0
- data/spec/base_type_spec.rb +167 -0
- data/spec/builders/c/buildable_spec.rb +25 -0
- data/spec/builders/c/composite_spec.rb +46 -0
- data/spec/builders/c/enumeration_spec.rb +32 -0
- data/spec/builders/c/fixed_array_spec.rb +36 -0
- data/spec/builders/c/group_spec.rb +112 -0
- data/spec/builders/c/scalar_spec.rb +8 -0
- data/spec/builders/c/variable_array_spec.rb +50 -0
- data/spec/builders_spec.rb +51 -0
- data/spec/c_builder_spec.rb +133 -0
- data/spec/cauterize_spec.rb +8 -0
- data/spec/composite_spec.rb +62 -0
- data/spec/enumeration_spec.rb +104 -0
- data/spec/fixed_array_spec.rb +62 -0
- data/spec/group_spec.rb +104 -0
- data/spec/scalar_spec.rb +36 -0
- data/spec/spec_helper.rb +115 -0
- data/spec/support/shared_examples_for_array_buildables.rb +22 -0
- data/spec/support/shared_examples_for_c_buildables.rb +91 -0
- data/spec/support/shared_examples_for_sane_c_buildables.rb +22 -0
- data/spec/support/shared_examples_for_stubbed_functions.rb +18 -0
- data/spec/test_main.c +13 -0
- data/spec/variable_array_spec.rb +92 -0
- metadata +212 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
include Cauterize::Builders::C
|
2
|
+
|
3
|
+
describe Cauterize::Builders::C do
|
4
|
+
describe Buildable do
|
5
|
+
subject { Buildable.new(:some_blueprint) }
|
6
|
+
|
7
|
+
describe "required methods" do
|
8
|
+
it "raises errors on required interfaces" do
|
9
|
+
lambda {
|
10
|
+
REQUIRED_METHODS.each do |m|
|
11
|
+
subject.send(m)
|
12
|
+
end
|
13
|
+
}.should raise_error /must implement/
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe :method_missing do
|
18
|
+
it "calls the original if method not required" do
|
19
|
+
lambda {
|
20
|
+
subject.is_not_defined
|
21
|
+
}.should raise_error NoMethodError
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
describe Cauterize::Builders::C::Composite do
|
2
|
+
let(:type_constructor) do
|
3
|
+
lambda do |name|
|
4
|
+
scalar(:int32)
|
5
|
+
composite(name) do |c|
|
6
|
+
c.field :an_int, :int32
|
7
|
+
c.field :another_int, :int32
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it_behaves_like "a buildable"
|
13
|
+
it_behaves_like "a sane buildable"
|
14
|
+
include_examples "no enum"
|
15
|
+
|
16
|
+
context "structure definition" do
|
17
|
+
let(:comp) do
|
18
|
+
scalar(:int32)
|
19
|
+
_c = composite(:foo) do |c|
|
20
|
+
c.field(:an_int, :int32)
|
21
|
+
end
|
22
|
+
|
23
|
+
Builders.get(:c, _c)
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".struct_proto" do
|
27
|
+
it "defines a structure prototype" do
|
28
|
+
f = default_formatter
|
29
|
+
comp.struct_proto(f)
|
30
|
+
f.to_s.should == "struct foo;"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe ".struct_defn" do
|
35
|
+
it "defines a structure definition" do
|
36
|
+
f = default_formatter
|
37
|
+
comp.struct_defn(f)
|
38
|
+
fs = f.to_s
|
39
|
+
|
40
|
+
fs.should match /struct foo/
|
41
|
+
fs.should match /int32 an_int;/
|
42
|
+
fs.should match /};/
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
describe Cauterize::Builders::C::Enumeration do
|
2
|
+
let(:type_constructor) { lambda {|name| enumeration(name)}}
|
3
|
+
|
4
|
+
it_behaves_like "a buildable"
|
5
|
+
it_behaves_like "a sane buildable"
|
6
|
+
include_examples "no struct"
|
7
|
+
|
8
|
+
describe ".enum_defn" do
|
9
|
+
let(:en) do
|
10
|
+
_e = enumeration(:foo) do |e|
|
11
|
+
e.value :aaa
|
12
|
+
e.value :bbb
|
13
|
+
e.value "QuickBrownFox".to_sym
|
14
|
+
end
|
15
|
+
|
16
|
+
f = default_formatter
|
17
|
+
Builders.get(:c, _e).enum_defn(f)
|
18
|
+
f.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
it "contains the enum name" do
|
22
|
+
en.should match /enum foo/
|
23
|
+
end
|
24
|
+
|
25
|
+
it "contains an entry for each value" do
|
26
|
+
en.should match /AAA = 0,/
|
27
|
+
en.should match /BBB = 1,/
|
28
|
+
en.should match /QUICK_BROWN_FOX = 2,/
|
29
|
+
en.should match /};/
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
describe Cauterize::Builders::C::FixedArray do
|
2
|
+
let(:type_constructor) do
|
3
|
+
scalar(:uint32_t)
|
4
|
+
lambda do |name|
|
5
|
+
fixed_array(name) do |a|
|
6
|
+
a.array_type :uint32_t
|
7
|
+
a.array_size 16
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it_behaves_like "a buildable"
|
13
|
+
include_examples "no enum"
|
14
|
+
include_examples "no struct"
|
15
|
+
|
16
|
+
context "an array buildable" do
|
17
|
+
let(:desc_instance) { type_constructor.call(:some_type_name) }
|
18
|
+
let(:formatter) { default_formatter }
|
19
|
+
subject { described_class.new(desc_instance) }
|
20
|
+
|
21
|
+
describe :render do
|
22
|
+
it "contains the name" do
|
23
|
+
t_name = subject.instance_variable_get(:@blueprint).array_type.name
|
24
|
+
subject.render.should match /#{t_name}/
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe :declare do
|
29
|
+
before { subject.declare(formatter, :some_sym) }
|
30
|
+
|
31
|
+
it "contains the name and a ;" do
|
32
|
+
formatter.to_s.should match /uint32_t some_sym\[16\]; \/\* some_type_name \*\//
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
describe Cauterize::Builders::C::Group do
|
2
|
+
let(:type_constructor) { lambda {|name| group(name)}}
|
3
|
+
|
4
|
+
it_behaves_like "a buildable"
|
5
|
+
it_behaves_like "a sane buildable"
|
6
|
+
include_examples "no enum"
|
7
|
+
|
8
|
+
context "enumeration for type tag" do
|
9
|
+
before do
|
10
|
+
scalar(:uint8_t)
|
11
|
+
@g = group!(:some_name) do |_g|
|
12
|
+
_g.field(:a, :uint8_t)
|
13
|
+
_g.field(:b, :uint8_t)
|
14
|
+
end
|
15
|
+
@b = Cauterize::Builders::C::Group.new(@g)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ".initialize" do
|
19
|
+
it "creates the enumeration tag" do
|
20
|
+
@b.instance_variable_get(:@tag_enum).class.name.should == "Cauterize::Enumeration"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "@tag_enum" do
|
25
|
+
it "contains a entry for each field in the group" do
|
26
|
+
e = @b.instance_variable_get(:@tag_enum)
|
27
|
+
e.values.keys.should =~ [ :GROUP_SOME_NAME_TYPE_A,
|
28
|
+
:GROUP_SOME_NAME_TYPE_B ]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe ".packer_defn" do
|
33
|
+
before do
|
34
|
+
f = default_formatter
|
35
|
+
@b.packer_defn(f)
|
36
|
+
@fs = f.to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
it "contains the enum packer" do
|
40
|
+
@fs.should match /Pack_group_some_name_type/
|
41
|
+
end
|
42
|
+
|
43
|
+
it "contains each tag" do
|
44
|
+
@fs.should match /GROUP_SOME_NAME_TYPE_A/
|
45
|
+
@fs.should match /GROUP_SOME_NAME_TYPE_B/
|
46
|
+
end
|
47
|
+
|
48
|
+
it "contains each field" do
|
49
|
+
@fs.should match /src->data\.a/
|
50
|
+
@fs.should match /src->data\.b/
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe ".unpacker_defn" do
|
55
|
+
before do
|
56
|
+
f = default_formatter
|
57
|
+
@b.unpacker_defn(f)
|
58
|
+
@fs = f.to_s
|
59
|
+
end
|
60
|
+
|
61
|
+
it "contains the enum unpacker" do
|
62
|
+
@fs.should match /Unpack_group_some_name_type/
|
63
|
+
end
|
64
|
+
|
65
|
+
it "contains each tag" do
|
66
|
+
@fs.should match /GROUP_SOME_NAME_TYPE_A/
|
67
|
+
@fs.should match /GROUP_SOME_NAME_TYPE_B/
|
68
|
+
end
|
69
|
+
|
70
|
+
it "contains each field" do
|
71
|
+
@fs.should match /dst->data\.a/
|
72
|
+
@fs.should match /dst->data\.b/
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "structure definition" do
|
78
|
+
let(:grp) do
|
79
|
+
scalar(:int32)
|
80
|
+
_g = group(:oof) do |g|
|
81
|
+
g.field(:aaa, :int32)
|
82
|
+
g.field(:bbb, :int32)
|
83
|
+
end
|
84
|
+
|
85
|
+
Builders.get(:c, _g)
|
86
|
+
end
|
87
|
+
|
88
|
+
describe ".struct_proto" do
|
89
|
+
it "defines a structure prototype" do
|
90
|
+
f = default_formatter
|
91
|
+
grp.struct_proto(f)
|
92
|
+
f.to_s.should == "struct oof;"
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe ".struct_defn" do
|
97
|
+
it "defines a structure definition" do
|
98
|
+
f = default_formatter
|
99
|
+
grp.struct_defn(f)
|
100
|
+
fs = f.to_s
|
101
|
+
|
102
|
+
fs.should match /struct oof/
|
103
|
+
fs.should match /enum group_oof_type tag;/
|
104
|
+
fs.should match /union/
|
105
|
+
fs.should match /int32 aaa;/
|
106
|
+
fs.should match /int32 bbb;/
|
107
|
+
fs.should match /} data;/
|
108
|
+
fs.should match /};/
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
describe Cauterize::Builders::C::VariableArray do
|
2
|
+
let(:type_constructor) do
|
3
|
+
lambda do |name|
|
4
|
+
scalar(:uint8_t)
|
5
|
+
variable_array(name) do |a|
|
6
|
+
a.array_type(:uint8_t)
|
7
|
+
a.array_size(8)
|
8
|
+
a.size_type(:uint8_t)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it_behaves_like "a buildable"
|
14
|
+
it_behaves_like "a sane buildable"
|
15
|
+
include_examples "no enum"
|
16
|
+
|
17
|
+
context "structure definition" do
|
18
|
+
let(:vara) do
|
19
|
+
scalar(:int32)
|
20
|
+
_a = variable_array(:va) do |a|
|
21
|
+
a.array_size(8)
|
22
|
+
a.array_type(:int32)
|
23
|
+
a.size_type(:int32)
|
24
|
+
end
|
25
|
+
|
26
|
+
Builders.get(:c, _a)
|
27
|
+
end
|
28
|
+
|
29
|
+
describe ".struct_proto" do
|
30
|
+
it "defines a structure prototype" do
|
31
|
+
f = default_formatter
|
32
|
+
vara.struct_proto(f)
|
33
|
+
f.to_s.should == "struct va;"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".struct_defn" do
|
38
|
+
it "defines a structure definition" do
|
39
|
+
f = default_formatter
|
40
|
+
vara.struct_defn(f)
|
41
|
+
fs = f.to_s
|
42
|
+
|
43
|
+
fs.should match /struct va/
|
44
|
+
fs.should match /int32 length;/
|
45
|
+
fs.should match /int32 data\[8\];/
|
46
|
+
fs.should match /};/
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
describe Cauterize::Builders do
|
2
|
+
describe "#register and #get" do
|
3
|
+
let(:s) { scalar(:uint8_t) }
|
4
|
+
before do
|
5
|
+
class X; def initialize(i); end; end
|
6
|
+
class Y; def initialize(i); end; end
|
7
|
+
|
8
|
+
# save the old list so that we can restore it later.
|
9
|
+
old_builders = nil
|
10
|
+
Cauterize::Builders.module_exec do
|
11
|
+
old_builders = @builders
|
12
|
+
@builders = nil
|
13
|
+
end
|
14
|
+
@old_builders = old_builders
|
15
|
+
end
|
16
|
+
|
17
|
+
after do
|
18
|
+
# restore the builders so as not to break any other tests
|
19
|
+
old_builders = @old_builders
|
20
|
+
Cauterize::Builders.module_exec do
|
21
|
+
@builders = old_builders
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it "saves and retrieves classes" do
|
26
|
+
Cauterize::Builders.register(:c, Cauterize::Scalar, X)
|
27
|
+
Cauterize::Builders.get(:c, s).class.should be X
|
28
|
+
end
|
29
|
+
|
30
|
+
it "handles multiple languages" do
|
31
|
+
Cauterize::Builders.register(:c, Cauterize::Scalar, X)
|
32
|
+
Cauterize::Builders.get(:c, s).class.should be X
|
33
|
+
|
34
|
+
Cauterize::Builders.register(:cs, Cauterize::Scalar, Y)
|
35
|
+
Cauterize::Builders.get(:cs, s).class.should be Y
|
36
|
+
end
|
37
|
+
|
38
|
+
it "raises an error on duplicate registrations" do
|
39
|
+
Cauterize::Builders.register(:c, Cauterize::Scalar, X)
|
40
|
+
lambda {
|
41
|
+
Cauterize::Builders.register(:c, Cauterize::Scalar, X)
|
42
|
+
}.should raise_error /already registered/
|
43
|
+
end
|
44
|
+
|
45
|
+
it "raises an error if no builder is registered" do
|
46
|
+
lambda {
|
47
|
+
Cauterize::Builders.get(:c, s)
|
48
|
+
}.should raise_error /unregistered/
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
describe Cauterize::CBuilder do
|
5
|
+
before do
|
6
|
+
@tempdir = Dir.mktmpdir
|
7
|
+
@h_path = File.join(@tempdir, "testing.h")
|
8
|
+
@c_path = File.join(@tempdir, "testing.c")
|
9
|
+
|
10
|
+
@cb = CBuilder.new(@h_path, @c_path, "testing")
|
11
|
+
end
|
12
|
+
after { FileUtils.rm_rf @tempdir }
|
13
|
+
|
14
|
+
describe :initialize do
|
15
|
+
it "saves the h and c paths" do
|
16
|
+
@cb.h.should == @h_path
|
17
|
+
@cb.c.should == @c_path
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe :build do
|
22
|
+
before do
|
23
|
+
scalar(:uint8_t)
|
24
|
+
scalar(:uint16_t)
|
25
|
+
scalar(:uint32_t)
|
26
|
+
|
27
|
+
fixed_array(:mac_address) do |fa|
|
28
|
+
fa.array_type :uint8_t
|
29
|
+
fa.array_size 6
|
30
|
+
end
|
31
|
+
|
32
|
+
variable_array(:mac_table) do |t|
|
33
|
+
t.array_type :mac_address
|
34
|
+
t.array_size 64
|
35
|
+
t.size_type :uint8_t
|
36
|
+
end
|
37
|
+
|
38
|
+
variable_array(:name) do |va|
|
39
|
+
va.array_type :uint8_t
|
40
|
+
va.size_type :uint8_t
|
41
|
+
va.array_size 32
|
42
|
+
end
|
43
|
+
|
44
|
+
enumeration(:gender) do |e|
|
45
|
+
e.value :male
|
46
|
+
e.value :female
|
47
|
+
end
|
48
|
+
|
49
|
+
composite(:place) do |c|
|
50
|
+
c.field :name, :name
|
51
|
+
c.field :elevation, :uint32_t
|
52
|
+
end
|
53
|
+
|
54
|
+
composite(:person) do |c|
|
55
|
+
c.field :first_name, :name
|
56
|
+
c.field :last_name, :name
|
57
|
+
c.field :gender, :gender
|
58
|
+
end
|
59
|
+
|
60
|
+
composite(:dog) do |c|
|
61
|
+
c.field :name, :name
|
62
|
+
c.field :gender, :gender
|
63
|
+
c.field :leg_count, :uint8_t
|
64
|
+
end
|
65
|
+
|
66
|
+
group(:creature) do |g|
|
67
|
+
g.field :person, :person
|
68
|
+
g.field :dog, :dog
|
69
|
+
end
|
70
|
+
|
71
|
+
@cb.build
|
72
|
+
@h_text = File.read(@cb.h)
|
73
|
+
@h_lines = @h_text.lines.to_a
|
74
|
+
@c_text = File.read(@cb.c)
|
75
|
+
@c_lines = @c_text.lines.to_a
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "header generation" do
|
79
|
+
it "prevents multiple inclusion in headers" do
|
80
|
+
@h_lines[0].should match /#ifndef TESTING_H_\d+/
|
81
|
+
@h_lines[1].should match /#define TESTING_H_\d+/
|
82
|
+
@h_lines.last.should match /#endif \/\* TESTING_H_\d+ \*\//
|
83
|
+
end
|
84
|
+
|
85
|
+
it "includes prototype information for all defined types" do
|
86
|
+
@h_text.should match "struct name;"
|
87
|
+
@h_text.should match "struct person;"
|
88
|
+
@h_text.should match "struct place;"
|
89
|
+
end
|
90
|
+
|
91
|
+
it "includes enumeration and structure definitions" do
|
92
|
+
@h_text.should match /gender/
|
93
|
+
@h_text.should match /MALE = 0/
|
94
|
+
@h_text.should match /FEMALE = 1/
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "c body generation" do
|
99
|
+
it "includes the generated header file" do
|
100
|
+
@c_text.should match /#include "testing.h"/
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "compilation" do
|
105
|
+
it "can be built" do
|
106
|
+
caut_dir = "#{File.dirname(__FILE__)}/../c/src"
|
107
|
+
|
108
|
+
res = Dir.chdir @tempdir do
|
109
|
+
File.open("test_main.c", "wb") do |fh|
|
110
|
+
syms = BaseType.all_instances.map do |i|
|
111
|
+
b = Builders.get(:c, i)
|
112
|
+
[b.packer_sym, b.unpacker_sym]
|
113
|
+
end.flatten
|
114
|
+
fh.write(gen_test_main(syms))
|
115
|
+
end
|
116
|
+
|
117
|
+
cmd = %W{
|
118
|
+
clang -Wall -Wextra -Werror
|
119
|
+
-I#{caut_dir}
|
120
|
+
#{@cb.c}
|
121
|
+
#{caut_dir}/cauterize.c
|
122
|
+
test_main.c
|
123
|
+
-o testing.bin 2>&1
|
124
|
+
}.join(" ")
|
125
|
+
|
126
|
+
`#{cmd}`
|
127
|
+
end
|
128
|
+
|
129
|
+
res.should == ""
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|