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.
Files changed (44) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +43 -0
  3. data/README.txt +102 -0
  4. data/Rakefile +25 -0
  5. data/examples/simple_assignment.rb +54 -0
  6. data/lib/treehouse.rb +52 -0
  7. data/lib/treehouse/metaid.rb +16 -0
  8. data/lib/treehouse/node.rb +79 -0
  9. data/lib/treehouse/node_creator.rb +28 -0
  10. data/lib/treehouse/node_definition.rb +106 -0
  11. data/lib/treehouse/visitor.rb +49 -0
  12. data/lib/treehouse/visitor_definition.rb +49 -0
  13. data/spec/fixtures/assignments.txt +7 -0
  14. data/spec/fixtures/ey00-s00348.xen +14 -0
  15. data/spec/grammars/assignments.rb +38 -0
  16. data/spec/grammars/assignments.treetop +42 -0
  17. data/spec/grammars/dot_xen.rb +122 -0
  18. data/spec/grammars/dot_xen.treetop +100 -0
  19. data/spec/grammars/magic.rb +63 -0
  20. data/spec/integration/assignments_spec.rb +45 -0
  21. data/spec/integration/dot_xen_spec.rb +86 -0
  22. data/spec/integration/magic_spec.rb +40 -0
  23. data/spec/node_creator_spec.rb +47 -0
  24. data/spec/node_definition_spec.rb +60 -0
  25. data/spec/node_spec.rb +131 -0
  26. data/spec/spec_helper.rb +34 -0
  27. data/spec/treehouse_spec.rb +17 -0
  28. data/spec/visitor_definition_spec.rb +44 -0
  29. data/spec/visitor_spec.rb +48 -0
  30. data/tasks/ann.rake +81 -0
  31. data/tasks/bones.rake +21 -0
  32. data/tasks/gem.rake +126 -0
  33. data/tasks/git.rake +41 -0
  34. data/tasks/manifest.rake +49 -0
  35. data/tasks/notes.rake +28 -0
  36. data/tasks/post_load.rake +39 -0
  37. data/tasks/rdoc.rake +51 -0
  38. data/tasks/rubyforge.rake +57 -0
  39. data/tasks/setup.rb +268 -0
  40. data/tasks/spec.rake +55 -0
  41. data/tasks/svn.rake +48 -0
  42. data/tasks/test.rake +38 -0
  43. data/treehouse.gemspec +38 -0
  44. 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
@@ -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
@@ -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