summaryrefslogtreecommitdiffstats
path: root/test/other/pgraph.rb
blob: e28decebb3346ed34d848c746046f28a6223cf0d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/usr/bin/env ruby
#
#  Created by Luke Kanies on 2006-11-16.
#  Copyright (c) 2006. All rights reserved.

$:.unshift("../lib").unshift("../../lib") if __FILE__ =~ /\.rb$/

require 'puppettest'
require 'puppettest/graph'

class TestPGraph < Test::Unit::TestCase
	include PuppetTest
	include PuppetTest::Graph
	
	Edge = Puppet::Relationship
	
	def test_clear
	    graph = Puppet::PGraph.new
	    graph.add_edge!("a", "b")
	    graph.add_vertex! "c"
	    assert_nothing_raised do
	        graph.clear
        end
        assert(graph.vertices.empty?, "Still have vertices after clear")
        assert(graph.edges.empty?, "still have edges after clear")
    end
	    
	
	def test_matching_edges
	    graph = Puppet::PGraph.new
	    
	    event = Puppet::Event.new(:source => "a", :event => :yay)
	    none = Puppet::Event.new(:source => "a", :event => :NONE)
	    
	    edges = {}
	    
	    edges["a/b"] = Edge["a", "b", {:event => :yay, :callback => :refresh}]
	    edges["a/c"] = Edge["a", "c", {:event => :yay, :callback => :refresh}]
	    
	    graph.add_edge!(edges["a/b"])
	    
	    # Try it for the trivial case of one target and a matching event
	    assert_equal([edges["a/b"]], graph.matching_edges([event]))
	    
	    # Make sure we get nothing with a different event
	    assert_equal([], graph.matching_edges([none]))
	    
	    # Set up multiple targets and make sure we get them all back
	    graph.add_edge!(edges["a/c"])
	    assert_equal([edges["a/b"], edges["a/c"]].sort, graph.matching_edges([event]).sort)
	    assert_equal([], graph.matching_edges([none]))
    end
    
    def test_dependencies
        graph = Puppet::PGraph.new
        
        graph.add_edge!("a", "b")
        graph.add_edge!("a", "c")
        graph.add_edge!("b", "d")
        
        assert_equal(%w{b c d}.sort, graph.dependents("a").sort)
        assert_equal(%w{d}.sort, graph.dependents("b").sort)
        assert_equal([].sort, graph.dependents("c").sort)
        
        assert_equal(%w{a b}, graph.dependencies("d").sort)
        assert_equal(%w{a}, graph.dependencies("b").sort)
        assert_equal(%w{a}, graph.dependencies("c").sort)
        assert_equal([], graph.dependencies("a").sort)
        
    end
    
    # Test that we can take a containment graph and rearrange it by dependencies
    def test_splice
        one, two, three, middle, top = build_tree
        empty = Container.new("empty", [])
        # Also, add an empty container to top
        top.push empty
        
        contgraph = top.to_graph
        
        # Now add a couple of child files, so that we can test whether all
        # containers get spliced, rather than just components.
        
        # Now make a dependency graph
        deps = Puppet::PGraph.new
        
        contgraph.vertices.each do |v|
            deps.add_vertex(v)
        end
        
        # We have to specify a relationship to our empty container, else it
        # never makes it into the dep graph in the first place.
        #{one => two, three => [middle, two, "c"], "f" => "c", "h" => middle, "c" => empty}.each do |source, targets|
        {one => two, "f" => "c", "h" => middle, "c" => empty}.each do |source, target|
            deps.add_edge!(source, target, :callback => :refresh)
        end

        #num = 6
        #contgraph.to_jpg(File.expand_path("~/tmp/graphs"), "containers#{num}")
        #contgraph.reversal.to_jpg(File.expand_path("~/tmp/graphs"), "reversal#{num}")
        #deps.to_jpg(File.expand_path("~/tmp/graphs"), "relationships#{num}")
        
        assert_nothing_raised { deps.splice!(contgraph, Container) }
        #deps.to_jpg(File.expand_path("~/tmp/graphs"), "after_relationships#{num}")
        
        assert(! deps.cyclic?, "Created a cyclic graph")

        # Make sure there are no container objects remaining
        c = deps.vertices.find_all { |v| v.is_a?(Container) }
        assert(c.empty?, "Still have containers %s" % c.inspect)
        
        # Now make sure the containers got spliced correctly.
        contgraph.leaves(middle).each do |leaf|
            assert(deps.edge?("h", leaf), "no edge for h => %s" % leaf)
        end
        one.each do |oobj|
            two.each do |tobj|
                assert(deps.edge?(oobj, tobj), "no %s => %s edge" % [oobj, tobj])
            end
        end
        
        nons = deps.vertices.find_all { |v| ! v.is_a?(String) }
        assert(nons.empty?,
            "still contain non-strings %s" % nons.inspect)
        
        deps.edges.each do |edge|
            assert_equal({:callback => :refresh}, edge.label,
                "Label was not copied for %s => %s" % [edge.source, edge.target])
        end

        # Now add some relationships to three, but only add labels to one of
        # the relationships.

        # Add a simple, label-less relationship
        deps.add_edge!(two, three)
        assert_nothing_raised { deps.splice!(contgraph, Container) }

        # And make sure it stuck, with no labels.
        assert_equal({}, deps.edge_label("c", "i"),
            "label was created for c => i")

        # Now add some edges with labels, in a way that should overwrite
        deps.add_edge!("c", three, {:callback => :refresh})
        assert_nothing_raised { deps.splice!(contgraph, Container) }

        # And make sure the label got copied.
        assert_equal({:callback => :refresh}, deps.edge_label("c", "i"),
            "label was not copied for c => i")

        # Lastly, add some new label-less edges and make sure the label stays.
        deps.add_edge!(middle, three)
        assert_nothing_raised { deps.splice!(contgraph, Container) }
        assert_equal({:callback => :refresh}, deps.edge_label("c", "i"),
            "label was lost for c => i")
        
        # Now make sure the 'three' edges all have the label we've used.
        # Note that this will not work when we support more than one type of
        # subscription.
        three.each do |child|
            edge = deps.edge_class.new("c", child)
            assert(deps.edge?(edge), "no c => %s edge" % child)
            assert_equal({:callback => :refresh}, deps[edge],
                "label was not retained for c => %s" % child)
        end
    end

    def test_copy_label
        graph = Puppet::PGraph.new

        # First make an edge with no label
        graph.add_edge!(:a, :b)
        assert_nil(graph.edge_label(:a, :b), "Created a label")

        # Now try to copy an empty label in.
        graph.copy_label(:a, :b, {})

        # It should just do nothing, since we copied an empty label.
        assert_nil(graph.edge_label(:a, :b), "Created a label")

        # Now copy in a real label.
        graph.copy_label(:a, :b, {:callback => :yay})
        assert_equal({:callback => :yay},
            graph.edge_label(:a, :b), "Did not copy label")

        # Now copy in a nil label
        graph.copy_label(:a, :b, nil)
        assert_equal({:callback => :yay},
            graph.edge_label(:a, :b), "lost label")

        # And an empty one.
        graph.copy_label(:a, :b, {})
        assert_equal({:callback => :yay},
            graph.edge_label(:a, :b), "lost label")
    end

    def test_check_cycle
        {
            {:a => :b, :b => :a} => true,
            {:a => :b, :b => :c, :c => :a} => true,
            {:a => :b, :b => :c} => false,
        }.each do |hash, result|
            graph = Puppet::PGraph.new
            hash.each do |a,b|
                graph.add_edge!(a, b)
            end

            if result
                assert_raise(Puppet::Error, "%s did not fail" % hash.inspect) do
                    graph.check_cycle
                end
            else
                assert_nothing_raised("%s failed" % hash.inspect) do
                    graph.check_cycle
                end
            end
        end
    end
end

# $Id$