| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2017 The LUCI Authors. All rights reserved. |
| 2 // Use of this source code is governed under the Apache License, Version 2.0 |
| 3 // that can be found in the LICENSE file. |
| 4 |
| 5 package python |
| 6 |
| 7 import ( |
| 8 "fmt" |
| 9 "sort" |
| 10 "testing" |
| 11 |
| 12 "github.com/luci/luci-go/common/data/rand/mathrand" |
| 13 |
| 14 "golang.org/x/net/context" |
| 15 |
| 16 . "github.com/luci/luci-go/common/testing/assertions" |
| 17 . "github.com/smartystreets/goconvey/convey" |
| 18 ) |
| 19 |
| 20 func TestParseVersion(t *testing.T) { |
| 21 t.Parallel() |
| 22 |
| 23 successes := []struct { |
| 24 input string |
| 25 v Version |
| 26 }{ |
| 27 {"", Version{}}, |
| 28 {"2", Version{2, 0, 0}}, |
| 29 {"2.7", Version{2, 7, 0}}, |
| 30 {"2.7.12", Version{2, 7, 12}}, |
| 31 {"1000.0.1", Version{1000, 0, 1}}, |
| 32 } |
| 33 |
| 34 failures := []struct { |
| 35 input string |
| 36 err string |
| 37 }{ |
| 38 {"a", "invalid number value"}, |
| 39 {"1.2.3.4", "unsupported number of parts"}, |
| 40 {"1.-2.1337", "must not be negative"}, |
| 41 {"0.1.2", "version is incomplete"}, |
| 42 {"1.1.X", "invalid patch value"}, |
| 43 {"1.Y.1", "invalid minor value"}, |
| 44 {"Y.1.1", "invalid major value"}, |
| 45 } |
| 46 |
| 47 Convey(`Testing ParseVersion`, t, func() { |
| 48 for _, tc := range successes { |
| 49 Convey(fmt.Sprintf(`Success: %q`, tc.input), func() { |
| 50 v, err := ParseVersion(tc.input) |
| 51 So(err, ShouldBeNil) |
| 52 So(v, ShouldResemble, tc.v) |
| 53 }) |
| 54 } |
| 55 |
| 56 for _, tc := range failures { |
| 57 Convey(fmt.Sprintf(`Failure: %q (%s)`, tc.input, tc.err)
, func() { |
| 58 _, err := ParseVersion(tc.input) |
| 59 So(err, ShouldErrLike, tc.err) |
| 60 }) |
| 61 } |
| 62 }) |
| 63 } |
| 64 |
| 65 func TestVersionSatisfied(t *testing.T) { |
| 66 t.Parallel() |
| 67 |
| 68 successes := []struct { |
| 69 base Version |
| 70 other Version |
| 71 }{ |
| 72 // Zero can be satisfied by anything. |
| 73 {Version{}, Version{1, 0, 0}}, |
| 74 {Version{}, Version{1, 1, 0}}, |
| 75 {Version{}, Version{1, 2, 3}}, |
| 76 |
| 77 // Major version matches. |
| 78 {Version{2, 0, 0}, Version{2, 0, 0}}, |
| 79 {Version{2, 0, 0}, Version{2, 7, 0}}, |
| 80 {Version{2, 0, 0}, Version{2, 7, 8}}, |
| 81 |
| 82 // Matching major, no patch, >= minor. |
| 83 {Version{2, 3, 0}, Version{2, 3, 0}}, |
| 84 {Version{2, 3, 0}, Version{2, 3, 1}}, |
| 85 {Version{2, 3, 0}, Version{2, 5, 0}}, |
| 86 |
| 87 // Matching major and minor, patch, >= minor. |
| 88 {Version{2, 3, 5}, Version{2, 5, 0}}, |
| 89 |
| 90 // Matching major and minor, >= patch. |
| 91 {Version{2, 3, 5}, Version{2, 3, 5}}, |
| 92 {Version{2, 3, 5}, Version{2, 3, 6}}, |
| 93 } |
| 94 |
| 95 failures := []struct { |
| 96 base Version |
| 97 other Version |
| 98 }{ |
| 99 // Zero cannot satisfy anything. |
| 100 {Version{}, Version{}}, |
| 101 {Version{1, 2, 3}, Version{}}, |
| 102 |
| 103 // Differing major versions. |
| 104 {Version{2, 0, 0}, Version{1, 0, 0}}, |
| 105 {Version{2, 0, 0}, Version{3, 0, 0}}, |
| 106 |
| 107 // Matching major, no patch, < minor. |
| 108 {Version{2, 3, 0}, Version{2, 2, 0}}, |
| 109 {Version{2, 3, 0}, Version{2, 2, 1000}}, |
| 110 |
| 111 // Matching major and minor, patch, < minor. |
| 112 {Version{2, 3, 5}, Version{2, 2, 1000}}, |
| 113 |
| 114 // Matching major and minor, < patch. |
| 115 {Version{2, 3, 5}, Version{2, 3, 0}}, |
| 116 {Version{2, 3, 5}, Version{2, 3, 4}}, |
| 117 } |
| 118 |
| 119 Convey(`Testing version satisfaction`, t, func() { |
| 120 for _, tc := range successes { |
| 121 Convey(fmt.Sprintf(`%q is satisfied by %q`, tc.base, tc.
other), func() { |
| 122 So(tc.base.IsSatisfiedBy(tc.other), ShouldBeTrue
) |
| 123 }) |
| 124 } |
| 125 |
| 126 for _, tc := range failures { |
| 127 Convey(fmt.Sprintf(`%q is NOT satisfied by %q`, tc.base,
tc.other), func() { |
| 128 So(tc.base.IsSatisfiedBy(tc.other), ShouldBeFals
e) |
| 129 }) |
| 130 } |
| 131 }) |
| 132 } |
| 133 |
| 134 func TestVersionLess(t *testing.T) { |
| 135 t.Parallel() |
| 136 |
| 137 Convey(`Testing "Less"`, t, func() { |
| 138 s := versionSlice{ |
| 139 {0, 0, 0}, |
| 140 {1, 0, 0}, |
| 141 {1, 0, 1}, |
| 142 {2, 0, 9}, |
| 143 {2, 6, 4}, |
| 144 {2, 7, 6}, |
| 145 {3, 0, 2}, |
| 146 {3, 1, 1}, |
| 147 {3, 4, 0}, |
| 148 } |
| 149 |
| 150 Convey(`Can sort.`, func() { |
| 151 cp := append(versionSlice(nil), s...) |
| 152 sort.Sort(cp) |
| 153 So(cp, ShouldResemble, s) |
| 154 }) |
| 155 |
| 156 Convey(`Can sort reversed.`, func() { |
| 157 cp := append(versionSlice(nil), s...) |
| 158 for i := 0; i < len(cp)/2; i++ { |
| 159 j := len(cp) - i - 1 |
| 160 cp[i], cp[j] = cp[j], cp[i] |
| 161 } |
| 162 |
| 163 sort.Sort(cp) |
| 164 So(cp, ShouldResemble, s) |
| 165 }) |
| 166 |
| 167 Convey(`Can sort randomized.`, func() { |
| 168 mr := mathrand.Get(context.Background()) |
| 169 cp := append(versionSlice(nil), s...) |
| 170 for i := range cp { |
| 171 j := mr.Intn(i + 1) |
| 172 cp[i], cp[j] = cp[j], cp[i] |
| 173 } |
| 174 |
| 175 sort.Sort(cp) |
| 176 So(cp, ShouldResemble, s) |
| 177 }) |
| 178 }) |
| 179 } |
| 180 |
| 181 type versionSlice []Version |
| 182 |
| 183 func (s versionSlice) Len() int { return len(s) } |
| 184 func (s versionSlice) Less(i, j int) bool { return s[i].Less(&s[j]) } |
| 185 func (s versionSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] } |
| OLD | NEW |