Merge lp:~thumper/juju-core/moar-checkers into lp:~go-bot/juju-core/trunk

Proposed by Tim Penhey
Status: Merged
Approved by: Tim Penhey
Approved revision: no longer in the source branch.
Merged at revision: 1311
Proposed branch: lp:~thumper/juju-core/moar-checkers
Merge into: lp:~go-bot/juju-core/trunk
Diff against target: 402 lines (+368/-0)
7 files modified
testing/checkers/bool.go (+35/-0)
testing/checkers/bool_test.go (+35/-0)
testing/checkers/checker_test.go (+27/-0)
testing/checkers/file.go (+98/-0)
testing/checkers/file_test.go (+97/-0)
testing/checkers/relop.go (+52/-0)
testing/checkers/relop_test.go (+24/-0)
To merge this branch: bzr merge lp:~thumper/juju-core/moar-checkers
Reviewer Review Type Date Requested Status
Juju Engineering Pending
Review via email: mp+170227@code.launchpad.net

Commit message

Some useful checkers.

Also some testing functions used later, with their own test.

https://codereview.appspot.com/10395044/

Description of the change

Some useful checkers.

Also some testing functions used later, with their own test.

https://codereview.appspot.com/10395044/

To post a comment you must log in.
Revision history for this message
Tim Penhey (thumper) wrote :

Reviewers: mp+170227_code.launchpad.net,

Message:
Please take a look.

Description:
Some useful checkers.

Also some testing functions used later, with their own test.

https://code.launchpad.net/~thumper/juju-core/moar-checkers/+merge/170227

(do not edit description out of merge proposal)

Please review this at https://codereview.appspot.com/10395044/

Affected files:
   A [revision details]
   A testing/checkers/bool.go
   A testing/checkers/bool_test.go
   A testing/checkers/checker_test.go
   A testing/checkers/relop.go
   A testing/checkers/relop_test.go
   A testing/file.go
   A testing/file_test.go

Revision history for this message
Tim Penhey (thumper) wrote :
Revision history for this message
Ian Booth (wallyworld) wrote :

LGTM

https://codereview.appspot.com/10395044/diff/3001/testing/checkers/bool.go
File testing/checkers/bool.go (right):

https://codereview.appspot.com/10395044/diff/3001/testing/checkers/bool.go#newcode27
testing/checkers/bool.go:27: return false, "obtained value not a bool"
If possible, also add the value and type to this error message, like for
the other greaterThan checker

https://codereview.appspot.com/10395044/

Revision history for this message
Tim Penhey (thumper) wrote :

Please take a look.

https://codereview.appspot.com/10395044/diff/3001/testing/checkers/bool.go
File testing/checkers/bool.go (right):

https://codereview.appspot.com/10395044/diff/3001/testing/checkers/bool.go#newcode27
testing/checkers/bool.go:27: return false, "obtained value not a bool"
On 2013/06/19 00:50:23, wallyworld wrote:
> If possible, also add the value and type to this error message, like
for the
> other greaterThan checker

Done.

https://codereview.appspot.com/10395044/

Revision history for this message
John A Meinel (jameinel) wrote :

LGTM

I have some comments about it, but the only one I really want to see
fixed is s/recieved/received/.

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool_test.go
File testing/checkers/bool_test.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool_test.go#newcode22
testing/checkers/bool_test.go:22: }
'received' which I think means you need to update the checker as well.

Would it be better to have the message:

expected "true" (type bool), received string: "foo"

Or to make the two halves consistent:

`expected type bool "true", received string "foo"`

I don't think you need the colon and to quote the string. Though I'm
soft on that.

Mostly, I'd like that if we are going to explicitly list what we
obtained, we should explicitly list what we expected.

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go
File testing/checkers/relop_test.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go#newcode24
testing/checkers/relop_test.go:24: }
I wonder if spelling this GreaterThan is best. Mostly because I'm
thinking of the permutations:
GreaterThanOrEqualTo

Which is pretty commonly abbreviated GTE.

I'm also hoping the infrastructure can give us a nice "Between" (though
again you have to watch out for whether one or both ends are open or
closed a < x < b vs a <= x < b, etc)

https://codereview.appspot.com/10395044/diff/7001/testing/file.go
File testing/file.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/file.go#newcode17
testing/file.go:17: }
Couldn't this be done as a checker too?

c.Assert(filename, IsNonEmptyFile) ?

I'm fine with this helper, but checkers do tend to be slightly more
consistent with how we do assertions.

Also, it lets you use "c.Check" when appropriate, rather than always
Assert (fail the test but apply more checks vs fail immediately and
stop).

https://codereview.appspot.com/10395044/

Revision history for this message
Tim Penhey (thumper) wrote :

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool_test.go
File testing/checkers/bool_test.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool_test.go#newcode22
testing/checkers/bool_test.go:22: }
On 2013/06/19 04:32:28, jameinel wrote:
> 'received' which I think means you need to update the checker as well.

> Would it be better to have the message:

> expected "true" (type bool), received string: "foo"

> Or to make the two halves consistent:

> `expected type bool "true", received string "foo"`

> I don't think you need the colon and to quote the string. Though I'm
soft on
> that.

> Mostly, I'd like that if we are going to explicitly list what we
obtained, we
> should explicitly list what we expected.

The quotes are part of %#v, so if we had

   42, that would become:
     int:42

Fixed received spelling, went for:

   `expected bool:true, received string:"foo"`
and added a test
   `expected bool:true, received int:42`

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go
File testing/checkers/relop_test.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go#newcode24
testing/checkers/relop_test.go:24: }
On 2013/06/19 04:32:28, jameinel wrote:
> I wonder if spelling this GreaterThan is best. Mostly because I'm
thinking of
> the permutations:
> GreaterThanOrEqualTo

> Which is pretty commonly abbreviated GTE.

> I'm also hoping the infrastructure can give us a nice "Between"
(though again
> you have to watch out for whether one or both ends are open or closed
a < x < b
> vs a <= x < b, etc)

python testtools uses GreaterThan too :)

Yes, you can do a between, and I do have one for time.

https://codereview.appspot.com/10395044/diff/7001/testing/file.go
File testing/file.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/file.go#newcode17
testing/file.go:17: }
On 2013/06/19 04:32:28, jameinel wrote:
> Couldn't this be done as a checker too?

> c.Assert(filename, IsNonEmptyFile) ?

> I'm fine with this helper, but checkers do tend to be slightly more
consistent
> with how we do assertions.

> Also, it lets you use "c.Check" when appropriate, rather than always
Assert
> (fail the test but apply more checks vs fail immediately and stop).

Yes... although I had trouble thinking of it at first.

Will fix.

https://codereview.appspot.com/10395044/

Revision history for this message
Frank Mueller (themue) wrote :

LGTM, thanks for moving it into an own CL.

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool.go
File testing/checkers/bool.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool.go#newcode13
testing/checkers/bool.go:13: // IsTrue checker
Not needed, for the other checkers too. But please add godoc comments
for the exported symbols like IsTrue or IsFalse.

https://codereview.appspot.com/10395044/

Revision history for this message
Roger Peppe (rogpeppe) wrote :

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool.go
File testing/checkers/bool.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/bool.go#newcode34
testing/checkers/bool.go:34: return false, fmt.Sprintf("expected type
bool, recieved %s:%#v", value.Kind(), params[0])
return false, fmt.Sprintf("expected type bool, received %s",
value.Type())

?
(gocheck itself will print the value for you - no need to print it
again).

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop.go
File testing/checkers/relop.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop.go#newcode51
testing/checkers/relop.go:51: return false, fmt.Sprintf("obtained value
%s:%#v not supported", p0value.Kind(), params[0])
fmt.Sprintf("expected numeric type, received %T", p0value)

?

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go
File testing/checkers/relop_test.go (right):

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go#newcode4
testing/checkers/relop_test.go:4: package checkers_test
i'm not sure we gain much by having a separate test file for each kind
of checker. i'd put them all in one file and test suite
(checkers_test.go), making it easy to scan 'em all at once.

https://codereview.appspot.com/10395044/diff/7001/testing/checkers/relop_test.go#newcode8
testing/checkers/relop_test.go:8: .
"launchpad.net/juju-core/testing/checkers"
I object to the spreading use of import to .

gocheck itself is bad enough.

Rather than polluting the local package name space,
could we choose a suitable short package identifier
or alias please? Or just use "checkers" itself.

if we adopted the fairly standard abbreviations
that john suggests, we could have something like:

c.Assert(45, checkers.GT, 42)

which isn't too much typing, and it's obvious where
the names come from.

https://codereview.appspot.com/10395044/

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'testing/checkers/bool.go'
2--- testing/checkers/bool.go 1970-01-01 00:00:00 +0000
3+++ testing/checkers/bool.go 2013-06-19 05:41:26 +0000
4@@ -0,0 +1,35 @@
5+// Copyright 2013 Canonical Ltd.
6+// Licensed under the AGPLv3, see LICENCE file for details.
7+
8+package checkers
9+
10+import (
11+ "fmt"
12+ "reflect"
13+
14+ . "launchpad.net/gocheck"
15+)
16+
17+// IsTrue checker
18+
19+type isTrueChecker struct {
20+ *CheckerInfo
21+}
22+
23+var IsTrue Checker = &isTrueChecker{
24+ &CheckerInfo{Name: "IsTrue", Params: []string{"obtained"}},
25+}
26+
27+var IsFalse Checker = Not(IsTrue)
28+
29+func (checker *isTrueChecker) Check(params []interface{}, names []string) (result bool, error string) {
30+
31+ value := reflect.ValueOf(params[0])
32+
33+ switch value.Kind() {
34+ case reflect.Bool:
35+ return value.Bool(), ""
36+ }
37+
38+ return false, fmt.Sprintf("expected bool:true, received %s:%#v", value.Kind(), params[0])
39+}
40
41=== added file 'testing/checkers/bool_test.go'
42--- testing/checkers/bool_test.go 1970-01-01 00:00:00 +0000
43+++ testing/checkers/bool_test.go 2013-06-19 05:41:26 +0000
44@@ -0,0 +1,35 @@
45+// Copyright 2013 Canonical Ltd.
46+// Licensed under the AGPLv3, see LICENCE file for details.
47+
48+package checkers_test
49+
50+import (
51+ . "launchpad.net/gocheck"
52+ . "launchpad.net/juju-core/testing/checkers"
53+)
54+
55+type BoolSuite struct{}
56+
57+var _ = Suite(&BoolSuite{})
58+
59+func (s *BoolSuite) TestIsTrue(c *C) {
60+ c.Assert(true, IsTrue)
61+ c.Assert(false, Not(IsTrue))
62+
63+ result, msg := IsTrue.Check([]interface{}{false}, nil)
64+ c.Assert(result, Equals, false)
65+ c.Assert(msg, Equals, "")
66+
67+ result, msg = IsTrue.Check([]interface{}{"foo"}, nil)
68+ c.Assert(result, Equals, false)
69+ c.Check(msg, Equals, `expected bool:true, received string:"foo"`)
70+
71+ result, msg = IsTrue.Check([]interface{}{42}, nil)
72+ c.Assert(result, Equals, false)
73+ c.Assert(msg, Equals, `expected bool:true, received int:42`)
74+}
75+
76+func (s *BoolSuite) TestIsFalse(c *C) {
77+ c.Assert(false, IsFalse)
78+ c.Assert(true, Not(IsFalse))
79+}
80
81=== added file 'testing/checkers/checker_test.go'
82--- testing/checkers/checker_test.go 1970-01-01 00:00:00 +0000
83+++ testing/checkers/checker_test.go 2013-06-19 05:41:26 +0000
84@@ -0,0 +1,27 @@
85+// Copyright 2013 Canonical Ltd.
86+// Licensed under the AGPLv3, see LICENCE file for details.
87+
88+package checkers_test
89+
90+import (
91+ "testing"
92+
93+ . "launchpad.net/gocheck"
94+ . "launchpad.net/juju-core/testing/checkers"
95+)
96+
97+func Test(t *testing.T) { TestingT(t) }
98+
99+type CheckerSuite struct{}
100+
101+var _ = Suite(&CheckerSuite{})
102+
103+func (s *CheckerSuite) TestHasPrefix(c *C) {
104+ c.Assert("foo bar", HasPrefix, "foo")
105+ c.Assert("foo bar", Not(HasPrefix), "omg")
106+}
107+
108+func (s *CheckerSuite) TestHasSuffix(c *C) {
109+ c.Assert("foo bar", HasSuffix, "bar")
110+ c.Assert("foo bar", Not(HasSuffix), "omg")
111+}
112
113=== added file 'testing/checkers/file.go'
114--- testing/checkers/file.go 1970-01-01 00:00:00 +0000
115+++ testing/checkers/file.go 2013-06-19 05:41:26 +0000
116@@ -0,0 +1,98 @@
117+// Copyright 2013 Canonical Ltd.
118+// Licensed under the AGPLv3, see LICENCE file for details.
119+
120+package checkers
121+
122+import (
123+ "fmt"
124+ "os"
125+ "reflect"
126+
127+ . "launchpad.net/gocheck"
128+)
129+
130+// IsNonEmptyFile checker
131+
132+type isNonEmptyFileChecker struct {
133+ *CheckerInfo
134+}
135+
136+var IsNonEmptyFile Checker = &isNonEmptyFileChecker{
137+ &CheckerInfo{Name: "IsNonEmptyFile", Params: []string{"obtained"}},
138+}
139+
140+func (checker *isNonEmptyFileChecker) Check(params []interface{}, names []string) (result bool, error string) {
141+ filename, isString := stringOrStringer(params[0])
142+ if isString {
143+ fileInfo, err := os.Stat(filename)
144+ if os.IsNotExist(err) {
145+ return false, fmt.Sprintf("%s does not exist", filename)
146+ } else if err != nil {
147+ return false, fmt.Sprintf("other stat error: %v", err)
148+ }
149+ if fileInfo.Size() > 0 {
150+ return true, ""
151+ } else {
152+ return false, fmt.Sprintf("%s is empty", filename)
153+ }
154+ }
155+
156+ value := reflect.ValueOf(params[0])
157+ return false, fmt.Sprintf("obtained value is not a string and has no .String(), %s:%#v", value.Kind(), params[0])
158+}
159+
160+// IsDirectory checker
161+
162+type isDirectoryChecker struct {
163+ *CheckerInfo
164+}
165+
166+var IsDirectory Checker = &isDirectoryChecker{
167+ &CheckerInfo{Name: "IsDirectory", Params: []string{"obtained"}},
168+}
169+
170+func (checker *isDirectoryChecker) Check(params []interface{}, names []string) (result bool, error string) {
171+ path, isString := stringOrStringer(params[0])
172+ if isString {
173+ fileInfo, err := os.Stat(path)
174+ if os.IsNotExist(err) {
175+ return false, fmt.Sprintf("%s does not exist", path)
176+ } else if err != nil {
177+ return false, fmt.Sprintf("other stat error: %v", err)
178+ }
179+ if fileInfo.IsDir() {
180+ return true, ""
181+ } else {
182+ return false, fmt.Sprintf("%s is not a directory", path)
183+ }
184+ }
185+
186+ value := reflect.ValueOf(params[0])
187+ return false, fmt.Sprintf("obtained value is not a string and has no .String(), %s:%#v", value.Kind(), params[0])
188+}
189+
190+// DoesNotExist checker makes sure the path specified doesn't exist.
191+
192+type doesNotExistChecker struct {
193+ *CheckerInfo
194+}
195+
196+var DoesNotExist Checker = &doesNotExistChecker{
197+ &CheckerInfo{Name: "DoesNotExist", Params: []string{"obtained"}},
198+}
199+
200+func (checker *doesNotExistChecker) Check(params []interface{}, names []string) (result bool, error string) {
201+ path, isString := stringOrStringer(params[0])
202+ if isString {
203+ _, err := os.Stat(path)
204+ if os.IsNotExist(err) {
205+ return true, ""
206+ } else if err != nil {
207+ return false, fmt.Sprintf("other stat error: %v", err)
208+ }
209+ return false, fmt.Sprintf("%s exists", path)
210+ }
211+
212+ value := reflect.ValueOf(params[0])
213+ return false, fmt.Sprintf("obtained value is not a string and has no .String(), %s:%#v", value.Kind(), params[0])
214+}
215
216=== added file 'testing/checkers/file_test.go'
217--- testing/checkers/file_test.go 1970-01-01 00:00:00 +0000
218+++ testing/checkers/file_test.go 2013-06-19 05:41:26 +0000
219@@ -0,0 +1,97 @@
220+// Copyright 2013 Canonical Ltd.
221+// Licensed under the AGPLv3, see LICENCE file for details.
222+
223+package checkers_test
224+
225+import (
226+ "fmt"
227+ "io/ioutil"
228+ "path/filepath"
229+
230+ . "launchpad.net/gocheck"
231+ . "launchpad.net/juju-core/testing/checkers"
232+)
233+
234+type FileSuite struct{}
235+
236+var _ = Suite(&FileSuite{})
237+
238+func (s *FileSuite) TestIsNonEmptyFile(c *C) {
239+ file, err := ioutil.TempFile(c.MkDir(), "")
240+ c.Assert(err, IsNil)
241+ fmt.Fprintf(file, "something")
242+ file.Close()
243+
244+ c.Assert(file.Name(), IsNonEmptyFile)
245+}
246+
247+func (s *FileSuite) TestIsNonEmptyFileWithEmptyFile(c *C) {
248+ file, err := ioutil.TempFile(c.MkDir(), "")
249+ c.Assert(err, IsNil)
250+ file.Close()
251+
252+ result, message := IsNonEmptyFile.Check([]interface{}{file.Name()}, nil)
253+ c.Assert(result, IsFalse)
254+ c.Assert(message, Equals, file.Name()+" is empty")
255+}
256+
257+func (s *FileSuite) TestIsNonEmptyFileWithMissingFile(c *C) {
258+ name := filepath.Join(c.MkDir(), "missing")
259+
260+ result, message := IsNonEmptyFile.Check([]interface{}{name}, nil)
261+ c.Assert(result, IsFalse)
262+ c.Assert(message, Equals, name+" does not exist")
263+}
264+
265+func (s *FileSuite) TestIsNonEmptyFileWithNumber(c *C) {
266+ result, message := IsNonEmptyFile.Check([]interface{}{42}, nil)
267+ c.Assert(result, IsFalse)
268+ c.Assert(message, Equals, "obtained value is not a string and has no .String(), int:42")
269+}
270+
271+func (s *FileSuite) TestIsDirectory(c *C) {
272+ dir := c.MkDir()
273+ c.Assert(dir, IsDirectory)
274+}
275+
276+func (s *FileSuite) TestIsDirectoryMissing(c *C) {
277+ absentDir := filepath.Join(c.MkDir(), "foo")
278+
279+ result, message := IsDirectory.Check([]interface{}{absentDir}, nil)
280+ c.Assert(result, IsFalse)
281+ c.Assert(message, Equals, absentDir+" does not exist")
282+}
283+
284+func (s *FileSuite) TestIsDirectoryWithFile(c *C) {
285+ file, err := ioutil.TempFile(c.MkDir(), "")
286+ c.Assert(err, IsNil)
287+ file.Close()
288+
289+ result, message := IsDirectory.Check([]interface{}{file.Name()}, nil)
290+ c.Assert(result, IsFalse)
291+ c.Assert(message, Equals, file.Name()+" is not a directory")
292+}
293+
294+func (s *FileSuite) TestIsDirectoryWithNumber(c *C) {
295+ result, message := IsDirectory.Check([]interface{}{42}, nil)
296+ c.Assert(result, IsFalse)
297+ c.Assert(message, Equals, "obtained value is not a string and has no .String(), int:42")
298+}
299+
300+func (s *FileSuite) TestDoesNotExist(c *C) {
301+ absentDir := filepath.Join(c.MkDir(), "foo")
302+ c.Assert(absentDir, DoesNotExist)
303+}
304+
305+func (s *FileSuite) TestDoesNotExistWithPath(c *C) {
306+ dir := c.MkDir()
307+ result, message := DoesNotExist.Check([]interface{}{dir}, nil)
308+ c.Assert(result, IsFalse)
309+ c.Assert(message, Equals, dir+" exists")
310+}
311+
312+func (s *FileSuite) TestDoesNotExistWithNumber(c *C) {
313+ result, message := DoesNotExist.Check([]interface{}{42}, nil)
314+ c.Assert(result, IsFalse)
315+ c.Assert(message, Equals, "obtained value is not a string and has no .String(), int:42")
316+}
317
318=== added file 'testing/checkers/relop.go'
319--- testing/checkers/relop.go 1970-01-01 00:00:00 +0000
320+++ testing/checkers/relop.go 2013-06-19 05:41:26 +0000
321@@ -0,0 +1,52 @@
322+// Copyright 2013 Canonical Ltd.
323+// Licensed under the AGPLv3, see LICENCE file for details.
324+
325+package checkers
326+
327+import (
328+ "fmt"
329+ "reflect"
330+
331+ . "launchpad.net/gocheck"
332+)
333+
334+// GreaterThan checker
335+
336+type greaterThanChecker struct {
337+ *CheckerInfo
338+}
339+
340+var GreaterThan Checker = &greaterThanChecker{
341+ &CheckerInfo{Name: "GreaterThan", Params: []string{"obtained", "expected"}},
342+}
343+
344+func (checker *greaterThanChecker) Check(params []interface{}, names []string) (result bool, error string) {
345+ defer func() {
346+ if v := recover(); v != nil {
347+ result = false
348+ error = fmt.Sprint(v)
349+ }
350+ }()
351+
352+ p0value := reflect.ValueOf(params[0])
353+ p1value := reflect.ValueOf(params[1])
354+ switch p0value.Kind() {
355+ case reflect.Int,
356+ reflect.Int8,
357+ reflect.Int16,
358+ reflect.Int32,
359+ reflect.Int64:
360+ return p0value.Int() > p1value.Int(), ""
361+ case reflect.Uint,
362+ reflect.Uint8,
363+ reflect.Uint16,
364+ reflect.Uint32,
365+ reflect.Uint64:
366+ return p0value.Uint() > p1value.Uint(), ""
367+ case reflect.Float32,
368+ reflect.Float64:
369+ return p0value.Float() > p1value.Float(), ""
370+ default:
371+ }
372+ return false, fmt.Sprintf("obtained value %s:%#v not supported", p0value.Kind(), params[0])
373+}
374
375=== added file 'testing/checkers/relop_test.go'
376--- testing/checkers/relop_test.go 1970-01-01 00:00:00 +0000
377+++ testing/checkers/relop_test.go 2013-06-19 05:41:26 +0000
378@@ -0,0 +1,24 @@
379+// Copyright 2013 Canonical Ltd.
380+// Licensed under the AGPLv3, see LICENCE file for details.
381+
382+package checkers_test
383+
384+import (
385+ . "launchpad.net/gocheck"
386+ . "launchpad.net/juju-core/testing/checkers"
387+)
388+
389+type RelopSuite struct{}
390+
391+var _ = Suite(&RelopSuite{})
392+
393+func (s *RelopSuite) TestGreaterThan(c *C) {
394+ c.Assert(45, GreaterThan, 42)
395+ c.Assert(2.25, GreaterThan, 1.0)
396+ c.Assert(42, Not(GreaterThan), 42)
397+ c.Assert(10, Not(GreaterThan), 42)
398+
399+ result, msg := GreaterThan.Check([]interface{}{"Hello", "World"}, nil)
400+ c.Assert(result, IsFalse)
401+ c.Assert(msg, Equals, `obtained value string:"Hello" not supported`)
402+}

Subscribers

People subscribed via source and target branches

to status/vote changes: