Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(204)

Delta Between Two Patch Sets: cmd/juju/plugin_test.go

Issue 9175043: state: testable transactions
Left Patch Set: Created 11 years, 11 months ago
Right Patch Set: state: testable transactions Created 11 years, 10 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Right: Side by side diff | Download
« no previous file with change/comment | « [revision details] ('k') | state/annotator.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
(no file at all)
1 // Copyright 2012, 2013 Canonical Ltd. 1 // Copyright 2012, 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package main 4 package main
5 5
6 import ( 6 import (
7 "bytes" 7 "bytes"
8 "fmt" 8 "fmt"
9 "io/ioutil" 9 "io/ioutil"
10 "os" 10 "os"
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 func (suite *PluginSuite) TestRunPluginWithFailing(c *C) { 85 func (suite *PluginSuite) TestRunPluginWithFailing(c *C) {
86 suite.makeFailingPlugin("foo", 2) 86 suite.makeFailingPlugin("foo", 2)
87 ctx := testing.Context(c) 87 ctx := testing.Context(c)
88 err := RunPlugin(ctx, "foo", []string{"some params"}) 88 err := RunPlugin(ctx, "foo", []string{"some params"})
89 c.Assert(err, ErrorMatches, "exit status 2") 89 c.Assert(err, ErrorMatches, "exit status 2")
90 c.Assert(testing.Stdout(ctx), Equals, "failing\n") 90 c.Assert(testing.Stdout(ctx), Equals, "failing\n")
91 c.Assert(testing.Stderr(ctx), Equals, "") 91 c.Assert(testing.Stderr(ctx), Equals, "")
92 } 92 }
93 93
94 func (suite *PluginSuite) TestGatherDescriptionsInParallel(c *C) { 94 func (suite *PluginSuite) TestGatherDescriptionsInParallel(c *C) {
95 » suite.makeFullPlugin(PluginParams{Name: "foo", Sleep: 100 * time.Millise cond}) 95 » // Make plugins that will deadlock if we don't start them in parallel.
96 » suite.makeFullPlugin(PluginParams{Name: "bar", Sleep: 150 * time.Millise cond}) 96 » // Each plugin depends on another one being started before they will
97 » suite.makeFullPlugin(PluginParams{Name: "baz", Sleep: 300 * time.Millise cond}) 97 » // complete. They make a full loop, so no sequential ordering will ever
98 » suite.makeFullPlugin(PluginParams{Name: "error", ExitStatus: 1, Sleep: 1 00 * time.Millisecond}) 98 » // succeed.
99 » suite.makeFullPlugin(PluginParams{Name: "slow", Sleep: 200 * time.Millis econd}) 99 » suite.makeFullPlugin(PluginParams{Name: "foo", Creates: "foo", DependsOn : "bar"})
100 100 » suite.makeFullPlugin(PluginParams{Name: "bar", Creates: "bar", DependsOn : "baz"})
101 » start := time.Now() 101 » suite.makeFullPlugin(PluginParams{Name: "baz", Creates: "baz", DependsOn : "error"})
102 » results := GetPluginDescriptions() 102 » suite.makeFullPlugin(PluginParams{Name: "error", ExitStatus: 1, Creates: "error", DependsOn: "foo"})
103 » elapsed := time.Since(start) 103
104 104 » // If the code was wrong, GetPluginDescriptions would deadlock,
105 » // 300 for baz above + 50ms wiggle room 105 » // so timeout after a short while
106 » expectedDuration := 350 * time.Millisecond 106 » resultChan := make(chan []PluginDescription)
107 107 » go func() {
108 » c.Assert(results, HasLen, 5) 108 » » resultChan <- GetPluginDescriptions()
109 » c.Check(elapsed, DurationLessThan, expectedDuration) 109 » }()
110 » // 10 seconds is arbitrary but should always be generously long. Test
111 » // actually only takes about 15ms in practice. But 10s allows for system hiccups, etc.
112 » waitTime := 10 * time.Second
113 » var results []PluginDescription
114 » select {
115 » case results = <-resultChan:
116 » » break
117 » case <-time.After(waitTime):
118 » » c.Fatalf("Took too more than %fs to complete.", waitTime.Seconds ())
119 » }
120
121 » c.Assert(results, HasLen, 4)
110 c.Assert(results[0].name, Equals, "bar") 122 c.Assert(results[0].name, Equals, "bar")
111 c.Assert(results[0].description, Equals, "bar description") 123 c.Assert(results[0].description, Equals, "bar description")
112 c.Assert(results[1].name, Equals, "baz") 124 c.Assert(results[1].name, Equals, "baz")
113 c.Assert(results[1].description, Equals, "baz description") 125 c.Assert(results[1].description, Equals, "baz description")
114 c.Assert(results[2].name, Equals, "error") 126 c.Assert(results[2].name, Equals, "error")
115 c.Assert(results[2].description, Equals, "error occurred running 'juju-e rror --description'") 127 c.Assert(results[2].description, Equals, "error occurred running 'juju-e rror --description'")
116 c.Assert(results[3].name, Equals, "foo") 128 c.Assert(results[3].name, Equals, "foo")
117 c.Assert(results[3].description, Equals, "foo description") 129 c.Assert(results[3].description, Equals, "foo description")
118 c.Assert(results[4].name, Equals, "slow")
119 c.Assert(results[4].description, Equals, "slow description")
120 } 130 }
121 131
122 func (suite *PluginSuite) TestHelpPluginsWithNoPlugins(c *C) { 132 func (suite *PluginSuite) TestHelpPluginsWithNoPlugins(c *C) {
123 output := badrun(c, 0, "help", "plugins") 133 output := badrun(c, 0, "help", "plugins")
124 c.Assert(output, HasPrefix, PluginTopicText) 134 c.Assert(output, HasPrefix, PluginTopicText)
125 c.Assert(output, HasSuffix, "\n\nNo plugins found.\n") 135 c.Assert(output, HasSuffix, "\n\nNo plugins found.\n")
126 } 136 }
127 137
128 func (suite *PluginSuite) TestHelpPluginsWithPlugins(c *C) { 138 func (suite *PluginSuite) TestHelpPluginsWithPlugins(c *C) {
129 suite.makeFullPlugin(PluginParams{Name: "foo"}) 139 suite.makeFullPlugin(PluginParams{Name: "foo"})
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 172
163 func (suite *PluginSuite) makeFailingPlugin(name string, exitStatus int) { 173 func (suite *PluginSuite) makeFailingPlugin(name string, exitStatus int) {
164 content := fmt.Sprintf("#!/bin/bash\necho failing\nexit %d", exitStatus) 174 content := fmt.Sprintf("#!/bin/bash\necho failing\nexit %d", exitStatus)
165 filename := testing.HomePath(JujuPluginPrefix + name) 175 filename := testing.HomePath(JujuPluginPrefix + name)
166 ioutil.WriteFile(filename, []byte(content), 0755) 176 ioutil.WriteFile(filename, []byte(content), 0755)
167 } 177 }
168 178
169 type PluginParams struct { 179 type PluginParams struct {
170 Name string 180 Name string
171 ExitStatus int 181 ExitStatus int
172 » Sleep time.Duration 182 » Creates string
183 » DependsOn string
173 } 184 }
174 185
175 const pluginTemplate = `#!/bin/bash 186 const pluginTemplate = `#!/bin/bash
176 187
177 if [ "$1" = "--description" ]; then 188 if [ "$1" = "--description" ]; then
178 sleep {{.Sleep.Seconds}} 189 if [ -n "{{.Creates}}" ]; then
190 touch "{{.Creates}}"
191 fi
192 if [ -n "{{.DependsOn}}" ]; then
193 # Sleep 10ms while waiting to allow other stuff to do work
194 while [ ! -e "{{.DependsOn}}" ]; do sleep 0.010; done
195 fi
179 echo "{{.Name}} description" 196 echo "{{.Name}} description"
180 exit {{.ExitStatus}} 197 exit {{.ExitStatus}}
198 else
199 echo "No --description" >2
181 fi 200 fi
182 201
183 if [ "$1" = "--help" ]; then 202 if [ "$1" = "--help" ]; then
184 echo "{{.Name}} longer help" 203 echo "{{.Name}} longer help"
185 echo "" 204 echo ""
186 echo "something useful" 205 echo "something useful"
187 exit {{.ExitStatus}} 206 exit {{.ExitStatus}}
188 fi 207 fi
189 208
190 echo {{.Name}} $* 209 echo {{.Name}} $*
191 exit {{.ExitStatus}} 210 exit {{.ExitStatus}}
192 ` 211 `
193 212
194 func (suite *PluginSuite) makeFullPlugin(params PluginParams) { 213 func (suite *PluginSuite) makeFullPlugin(params PluginParams) {
195 // Create a new template and parse the plugin into it. 214 // Create a new template and parse the plugin into it.
196 t := template.Must(template.New("plugin").Parse(pluginTemplate)) 215 t := template.Must(template.New("plugin").Parse(pluginTemplate))
197 content := &bytes.Buffer{} 216 content := &bytes.Buffer{}
217 filename := testing.HomePath("juju-" + params.Name)
218 // Create the files in the temp dirs, so we don't pollute the working sp ace
219 if params.Creates != "" {
220 params.Creates = testing.HomePath(params.Creates)
221 }
222 if params.DependsOn != "" {
223 params.DependsOn = testing.HomePath(params.DependsOn)
224 }
198 t.Execute(content, params) 225 t.Execute(content, params)
199 filename := testing.HomePath("juju-" + params.Name)
200 ioutil.WriteFile(filename, content.Bytes(), 0755) 226 ioutil.WriteFile(filename, content.Bytes(), 0755)
201 } 227 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b