aniero-treehouse 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/Manifest.txt +43 -0
- data/README.txt +102 -0
- data/Rakefile +25 -0
- data/examples/simple_assignment.rb +54 -0
- data/lib/treehouse.rb +52 -0
- data/lib/treehouse/metaid.rb +16 -0
- data/lib/treehouse/node.rb +79 -0
- data/lib/treehouse/node_creator.rb +28 -0
- data/lib/treehouse/node_definition.rb +106 -0
- data/lib/treehouse/visitor.rb +49 -0
- data/lib/treehouse/visitor_definition.rb +49 -0
- data/spec/fixtures/assignments.txt +7 -0
- data/spec/fixtures/ey00-s00348.xen +14 -0
- data/spec/grammars/assignments.rb +38 -0
- data/spec/grammars/assignments.treetop +42 -0
- data/spec/grammars/dot_xen.rb +122 -0
- data/spec/grammars/dot_xen.treetop +100 -0
- data/spec/grammars/magic.rb +63 -0
- data/spec/integration/assignments_spec.rb +45 -0
- data/spec/integration/dot_xen_spec.rb +86 -0
- data/spec/integration/magic_spec.rb +40 -0
- data/spec/node_creator_spec.rb +47 -0
- data/spec/node_definition_spec.rb +60 -0
- data/spec/node_spec.rb +131 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/treehouse_spec.rb +17 -0
- data/spec/visitor_definition_spec.rb +44 -0
- data/spec/visitor_spec.rb +48 -0
- data/tasks/ann.rake +81 -0
- data/tasks/bones.rake +21 -0
- data/tasks/gem.rake +126 -0
- data/tasks/git.rake +41 -0
- data/tasks/manifest.rake +49 -0
- data/tasks/notes.rake +28 -0
- data/tasks/post_load.rake +39 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +57 -0
- data/tasks/setup.rb +268 -0
- data/tasks/spec.rake +55 -0
- data/tasks/svn.rake +48 -0
- data/tasks/test.rake +38 -0
- data/treehouse.gemspec +38 -0
- metadata +124 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
require Treehouse.path(%w(spec grammars assignments))
|
4
|
+
|
5
|
+
describe AssignmentsLanguage::Grammar do
|
6
|
+
|
7
|
+
it "has nodes defined" do
|
8
|
+
consts = AssignmentsLanguage::Grammar.constants
|
9
|
+
consts.should include("Assignments")
|
10
|
+
consts.should include("Assignment")
|
11
|
+
consts.should include("BlankLine")
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
describe AssignmentsLanguage::Parser, ".parse" do
|
17
|
+
|
18
|
+
before(:each) do
|
19
|
+
@input = File.read(Treehouse.path(%w(spec fixtures assignments.txt)))
|
20
|
+
end
|
21
|
+
|
22
|
+
it "parses a file and returns a Treehouse AST" do
|
23
|
+
AssignmentsLanguage::Parser.parse(@input).should be_a_kind_of(Treehouse::Node)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
describe AssignmentsLanguage do
|
29
|
+
it "has a string visitor defined" do
|
30
|
+
AssignmentsLanguage.const_get("StringVisitor").ancestors.should include(Treehouse::Visitor)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe AssignmentsLanguage::StringVisitor do
|
35
|
+
before(:each) do
|
36
|
+
@input = File.read(Treehouse.path(%w(spec fixtures assignments.txt)))
|
37
|
+
@ast = AssignmentsLanguage::Parser.parse(@input)
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#visit" do
|
41
|
+
it "traverses the AST and collects the values" do
|
42
|
+
AssignmentsLanguage::StringVisitor.visit(@ast).should == "foo = bar\nbaz = blech\nno = way\n"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
require Treehouse.path(%w(spec grammars dot_xen))
|
4
|
+
|
5
|
+
describe DotXen::Parser, ".parse" do
|
6
|
+
before(:each) do
|
7
|
+
data = File.read(Treehouse.path(%w(spec fixtures ey00-s00348.xen)))
|
8
|
+
@ast = DotXen::Parser.parse(data)
|
9
|
+
end
|
10
|
+
it "returns an AST" do
|
11
|
+
@ast.should_not be_nil
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "with a parsed AST" do
|
15
|
+
it "has a comment" do
|
16
|
+
@ast.should have(1).comments
|
17
|
+
end
|
18
|
+
|
19
|
+
it "has 3 disks" do
|
20
|
+
@ast.should have(3).disks
|
21
|
+
end
|
22
|
+
|
23
|
+
it "has vars" do
|
24
|
+
@ast.should have_at_least(5).vars
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe DotXen::HashVisitor do
|
32
|
+
before(:all) do
|
33
|
+
data = File.read(Treehouse.path(%w(spec fixtures ey00-s00348.xen)))
|
34
|
+
@ast = DotXen::Parser.parse(data)
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".visit" do
|
38
|
+
it "returns a hash representation of the AST" do
|
39
|
+
DotXen::HashVisitor.visit(@ast).should == {
|
40
|
+
:comments => [" -*- mode: python; -*-"],
|
41
|
+
:disks => [
|
42
|
+
"phy:/dev/ey00-data4/root-s00348,sda1,w",
|
43
|
+
"phy:/dev/ey00-data4/swap-s00348,sda2,w",
|
44
|
+
"phy:/dev/ey00-data4/gfs-00218,sdb1,w!"
|
45
|
+
],
|
46
|
+
:vars => {
|
47
|
+
"name" => "ey00-s00348",
|
48
|
+
"kernel" => "/boot/vmlinuz-2.6.18-xenU",
|
49
|
+
"memory" => 712,
|
50
|
+
"cpu_cap" => 100,
|
51
|
+
"vcpus" => 1,
|
52
|
+
"root" => "/dev/sda1 ro",
|
53
|
+
"maxmem" => 4096,
|
54
|
+
"vif" => ["bridge=xenbr0"]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe DotXen::StringVisitor do
|
62
|
+
before(:all) do
|
63
|
+
data = File.read(Treehouse.path(%w(spec fixtures ey00-s00348.xen)))
|
64
|
+
@ast = DotXen::Parser.parse(data)
|
65
|
+
end
|
66
|
+
describe ".visit" do
|
67
|
+
it "returns a string representation of the AST" do
|
68
|
+
DotXen::StringVisitor.visit(@ast).should == <<-EOS
|
69
|
+
# -*- mode: python; -*-
|
70
|
+
kernel = '/boot/vmlinuz-2.6.18-xenU'
|
71
|
+
memory = 712
|
72
|
+
maxmem = 4096
|
73
|
+
name = 'ey00-s00348'
|
74
|
+
vif = [ 'bridge=xenbr0' ]
|
75
|
+
root = "/dev/sda1 ro"
|
76
|
+
vcpus = 1
|
77
|
+
cpu_cap = 100
|
78
|
+
disk = [
|
79
|
+
"phy:/dev/ey00-data4/root-s00348,sda1,w",
|
80
|
+
"phy:/dev/ey00-data4/swap-s00348,sda2,w",
|
81
|
+
"phy:/dev/ey00-data4/gfs-00218,sdb1,w!"
|
82
|
+
]
|
83
|
+
EOS
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[.. spec_helper])
|
2
|
+
|
3
|
+
require Treehouse.path(%w(spec grammars magic))
|
4
|
+
|
5
|
+
describe MagicAssignments::Parser do
|
6
|
+
describe ".parse" do
|
7
|
+
before(:each) do
|
8
|
+
@input = File.read(Treehouse.path(%w(spec fixtures assignments.txt)))
|
9
|
+
@result = MagicAssignments::Parser.parse(@input)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "returns an AST" do
|
13
|
+
@result.should be_an_instance_of(MagicAssignments::AST::Assignments)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "has the right number of nodes" do
|
17
|
+
@result.should have(7).assignments
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has an assignment with correct values" do
|
21
|
+
@result.assignments.first.should be_an_instance_of(MagicAssignments::AST::Assignment)
|
22
|
+
@result.assignments.first.lhs.value.should == "foo"
|
23
|
+
@result.assignments.first.rhs.value.should == "bar"
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe MagicAssignments::HashVisitor do
|
30
|
+
describe ".visit" do
|
31
|
+
it "returns a hash representation of the assignments" do
|
32
|
+
ast = MagicAssignments::Parser.parse(File.read(Treehouse.path(%w(spec fixtures assignments.txt))))
|
33
|
+
MagicAssignments::HashVisitor.visit(ast).should == {
|
34
|
+
"foo" => "bar",
|
35
|
+
"baz" => "blech",
|
36
|
+
"no" => "way"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Treehouse::NodeCreator do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
SomeNode = Class.new(Treehouse::Node)
|
7
|
+
end
|
8
|
+
after(:all) do
|
9
|
+
Object.send(:remove_const, "SomeNode")
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
|
14
|
+
it "takes a class as an argument" do
|
15
|
+
nc = Treehouse::NodeCreator.new(SomeNode)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#new" do
|
20
|
+
before(:each) do
|
21
|
+
@nc = Treehouse::NodeCreator.new(SomeNode)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "takes parameters as if it were a treetop syntax node" do
|
25
|
+
@nc.new("what", 0..3)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "returns a treetop syntax node" do
|
29
|
+
node = @nc.new("what", 0..3)
|
30
|
+
node.should be_an_instance_of(Treetop::Runtime::SyntaxNode)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "defines a build method on the syntax node" do
|
34
|
+
node = @nc.new("what", 0..3)
|
35
|
+
node.methods.should include("build")
|
36
|
+
end
|
37
|
+
|
38
|
+
it "creates an instance of the defined class when build is called on the resulting syntax node" do
|
39
|
+
node = @nc.new("what", 0..3)
|
40
|
+
mock_node = mock("node")
|
41
|
+
SomeNode.should_receive(:new).with(node).and_return(mock_node)
|
42
|
+
node.build.should == mock_node
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Treehouse::NodeDefinition do
|
4
|
+
module TestNodes
|
5
|
+
include Treehouse::NodeDefinition
|
6
|
+
end
|
7
|
+
|
8
|
+
it "adds a node method when included" do
|
9
|
+
TestNodes.methods.should include("node")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "adds a create_node method when included" do
|
13
|
+
TestNodes.methods.should include("create_node")
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".node" do
|
17
|
+
before(:each) do
|
18
|
+
TestNodes.class_eval { node :foo, :bar, :baz }
|
19
|
+
end
|
20
|
+
after(:each) do
|
21
|
+
TestNodes.send(:remove_const, "Foo")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "defines a class" do
|
25
|
+
TestNodes.constants.should include("Foo")
|
26
|
+
TestNodes::Foo.ancestors.should include(Treehouse::Node)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "defines a class with an attribute for each of the provided arguments" do
|
30
|
+
TestNodes::Foo.instance_methods.should include("bar")
|
31
|
+
TestNodes::Foo.instance_methods.should include("baz")
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
describe ".create_node" do
|
37
|
+
before(:all) do
|
38
|
+
TestNodes.class_eval { node :foo_node }
|
39
|
+
end
|
40
|
+
after(:all) do
|
41
|
+
TestNodes.send(:remove_const, "FooNode")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "takes a node name as an argument" do
|
45
|
+
TestNodes.create_node(:foo_node)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns an instance of NodeCreator" do
|
49
|
+
TestNodes.create_node(:foo_node).should be_an_instance_of(Treehouse::NodeCreator)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "instantiates the node creator with the class corresponding to the node name" do
|
53
|
+
obj = Object.new
|
54
|
+
Treehouse::NodeCreator.should_receive(:new).with(TestNodes::FooNode).and_return(obj)
|
55
|
+
TestNodes.create_node(:foo_node).should == obj
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/spec/node_spec.rb
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Treehouse::Node do
|
4
|
+
|
5
|
+
describe ".create" do
|
6
|
+
it "returns a class that inherits from Treehouse::Node" do
|
7
|
+
klass = Treehouse::Node.create
|
8
|
+
klass.should be_an_instance_of(Class)
|
9
|
+
klass.ancestors.should include(Treehouse::Node)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "with attribute names" do
|
13
|
+
before(:each) do
|
14
|
+
@node = Treehouse::Node.create(:foo, :bar)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "creates a class with the given attributes" do
|
18
|
+
n = @node.new(:foo => 1, :bar => 2)
|
19
|
+
n.foo.should == 1
|
20
|
+
n.bar.should == 2
|
21
|
+
end
|
22
|
+
|
23
|
+
it "creates attributes with a default of raising an exception if not initialized" do
|
24
|
+
n = @node.new(:foo => 1) # no :bar
|
25
|
+
n.foo.should == 1
|
26
|
+
lambda { n.bar }.should raise_error(RuntimeError, "no value given for bar")
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "with an attribute hash" do
|
32
|
+
before(:each) do
|
33
|
+
@node = Treehouse::Node.create(:lhs => :left_value, :rhs => :right_value)
|
34
|
+
end
|
35
|
+
|
36
|
+
it "creates a class with attributes matching the hash keys" do
|
37
|
+
@node.attributes.sort.should == ["lhs", "rhs"]
|
38
|
+
end
|
39
|
+
|
40
|
+
it "creates attributes with a default of raising an exception if not set" do
|
41
|
+
n = @node.new
|
42
|
+
lambda { n.lhs }.should raise_error(RuntimeError, "no value given for lhs")
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns a class with an attribute mapping" do
|
46
|
+
@node.attribute_mapping.should == {"lhs" => :left_value, "rhs" => :right_value}
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "with a mix of named attributes and hash attributes" do
|
52
|
+
before(:each) do
|
53
|
+
@node = Treehouse::Node.create(:one, :two, :three => :value)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "creates a class with attributes matching the named attributes and hash keys" do
|
57
|
+
@node.attributes.should == %w(one two three)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "updates the attribute mapping" do
|
61
|
+
@node.attribute_mapping.should == {"three" => :value}
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
describe ".new" do
|
69
|
+
before(:each) do
|
70
|
+
@node = Treehouse::Node.create(:child, :value => :data)
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "with empty args" do
|
74
|
+
it "initializes a node without touching the attributes" do
|
75
|
+
n = @node.new
|
76
|
+
lambda { n.child }.should raise_error(RuntimeError)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "with a hash" do
|
81
|
+
it "initializes each of the attributes to the given value" do
|
82
|
+
n = @node.new(:child => 1, :value => 2)
|
83
|
+
n.child.should == 1
|
84
|
+
n.value.should == 2
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "with an instance of Treetop::Runtime::SyntaxNode" do
|
89
|
+
before(:each) do
|
90
|
+
@child = mock_syntax_node :build => "child value"
|
91
|
+
@top = mock_syntax_node :child => @child, :data => "data"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "sets the named values by calling build on the named child node" do
|
95
|
+
@top.should_receive(:child).and_return(@child)
|
96
|
+
@child.should_receive(:build).and_return("child value")
|
97
|
+
n = @node.new(@top)
|
98
|
+
n.child.should == "child value"
|
99
|
+
end
|
100
|
+
|
101
|
+
it "calls the specified method directly for hash values" do
|
102
|
+
@top.should_receive(:data).and_return do
|
103
|
+
puts "called from #{caller.detect {|c| c !~ /rspec/}}"
|
104
|
+
"foo"
|
105
|
+
end
|
106
|
+
n = @node.new(@top)
|
107
|
+
n.value.should == "foo"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "calls build on each element of a referenced node value if that value is an array" do
|
111
|
+
@top.should_receive(:child).and_return([@child, @child])
|
112
|
+
@child.should_receive(:build).exactly(2).times.and_return("one", "two")
|
113
|
+
n = @node.new(@top)
|
114
|
+
n.child.should == %w(one two)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "only calls build on elements of an array if they respond to that method" do
|
118
|
+
@top.should_receive(:child).and_return([@child, "blah"])
|
119
|
+
@node.new(@top).child.should == ["child value", "blah"]
|
120
|
+
end
|
121
|
+
|
122
|
+
it "yields the syntax node instance if a mapped attribute is a lambda" do
|
123
|
+
@node = Treehouse::Node.create(:value => lambda { |x| @x = x })
|
124
|
+
@node.new(@top)
|
125
|
+
@x.should == @top
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), %w[.. lib treehouse]))
|
2
|
+
|
3
|
+
Spec::Runner.configure do |config|
|
4
|
+
# == Mock Framework
|
5
|
+
#
|
6
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
7
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
8
|
+
#
|
9
|
+
# config.mock_with :mocha
|
10
|
+
# config.mock_with :flexmock
|
11
|
+
# config.mock_with :rr
|
12
|
+
|
13
|
+
# borrowed from rspec_on_rails' mock_model
|
14
|
+
def mock_syntax_node(stubs={})
|
15
|
+
m = mock "mock syntax node", stubs
|
16
|
+
m.send(:__mock_proxy).instance_eval do
|
17
|
+
def @target.is_a?(other)
|
18
|
+
Treetop::Runtime::SyntaxNode.ancestors.include?(other)
|
19
|
+
end
|
20
|
+
def @target.kind_of?(other)
|
21
|
+
Treetop::Runtime::SyntaxNode.ancestors.include?(other)
|
22
|
+
end
|
23
|
+
def @target.instance_of?(other)
|
24
|
+
other == Treetop::Runtime::SyntaxNode
|
25
|
+
end
|
26
|
+
def @target.class
|
27
|
+
Treetop::Runtime::SyntaxNode
|
28
|
+
end
|
29
|
+
end
|
30
|
+
yield m if block_given?
|
31
|
+
m
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|