github.com/pingcap/ticdc@v0.0.0-20220526033649-485a10ef2652/pkg/version/check_test.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package version 15 16 import ( 17 "context" 18 "fmt" 19 "net/http" 20 "net/url" 21 "testing" 22 "time" 23 24 "github.com/coreos/go-semver/semver" 25 "github.com/pingcap/check" 26 "github.com/pingcap/kvproto/pkg/metapb" 27 "github.com/pingcap/ticdc/cdc/model" 28 "github.com/pingcap/ticdc/pkg/util/testleak" 29 pd "github.com/tikv/pd/client" 30 "github.com/tikv/pd/pkg/tempurl" 31 ) 32 33 func Test(t *testing.T) { 34 check.TestingT(t) 35 } 36 37 type checkSuite struct{} 38 39 var _ = check.Suite(&checkSuite{}) 40 41 type mockPDClient struct { 42 pd.Client 43 getAllStores func() []*metapb.Store 44 getVersion func() string 45 getStatusCode func() int 46 } 47 48 func (m *mockPDClient) GetAllStores(ctx context.Context, opts ...pd.GetStoreOption) ([]*metapb.Store, error) { 49 if m.getAllStores != nil { 50 return m.getAllStores(), nil 51 } 52 return []*metapb.Store{}, nil 53 } 54 55 func (m *mockPDClient) ServeHTTP(resp http.ResponseWriter, _ *http.Request) { 56 // set status code at first, else will not work 57 if m.getStatusCode != nil { 58 resp.WriteHeader(m.getStatusCode()) 59 } 60 61 if m.getVersion != nil { 62 _, _ = resp.Write([]byte(fmt.Sprintf(`{"version":"%s"}`, m.getVersion()))) 63 } 64 } 65 66 func (s *checkSuite) TestCheckClusterVersion(c *check.C) { 67 defer testleak.AfterTest(c)() 68 mock := mockPDClient{ 69 Client: nil, 70 } 71 pdURL, _ := url.Parse(tempurl.Alloc()) 72 pdHTTP := fmt.Sprintf("http://%s", pdURL.Host) 73 srv := http.Server{Addr: pdURL.Host, Handler: &mock} 74 go func() { 75 //nolint:errcheck 76 srv.ListenAndServe() 77 }() 78 defer srv.Close() 79 for i := 0; i < 20; i++ { 80 time.Sleep(100 * time.Millisecond) 81 _, err := http.Get(pdHTTP) 82 if err == nil { 83 break 84 } 85 c.Error(err) 86 if i == 19 { 87 c.Fatal("http server timeout", err) 88 } 89 } 90 91 { 92 mock.getVersion = func() string { 93 return minPDVersion.String() 94 } 95 mock.getAllStores = func() []*metapb.Store { 96 return []*metapb.Store{{Version: MinTiKVVersion.String()}} 97 } 98 err := CheckClusterVersion(context.Background(), &mock, pdHTTP, nil, true) 99 c.Assert(err, check.IsNil) 100 } 101 102 { 103 mock.getVersion = func() string { 104 return `v1.0.0-alpha-271-g824ae7fd` 105 } 106 mock.getAllStores = func() []*metapb.Store { 107 return []*metapb.Store{{Version: MinTiKVVersion.String()}} 108 } 109 err := CheckClusterVersion(context.Background(), &mock, pdHTTP, nil, true) 110 c.Assert(err, check.ErrorMatches, 111 ".*PD .* is not supported.*") 112 } 113 114 { 115 mock.getVersion = func() string { 116 return minPDVersion.String() 117 } 118 mock.getAllStores = func() []*metapb.Store { 119 // TiKV does not include 'v'. 120 return []*metapb.Store{{Version: `1.0.0-alpha-271-g824ae7fd`}} 121 } 122 err := CheckClusterVersion(context.Background(), &mock, pdHTTP, nil, true) 123 c.Assert(err, check.ErrorMatches, 124 ".*TiKV .* is not supported.*") 125 err = CheckClusterVersion(context.Background(), &mock, pdHTTP, nil, false) 126 c.Assert(err, check.IsNil) 127 } 128 129 { 130 mock.getStatusCode = func() int { 131 return http.StatusBadRequest 132 } 133 134 err := CheckClusterVersion(context.Background(), &mock, pdHTTP, nil, false) 135 c.Assert(err, check.ErrorMatches, ".*response status: .*") 136 } 137 } 138 139 func (s *checkSuite) TestCompareVersion(c *check.C) { 140 defer testleak.AfterTest(c)() 141 c.Assert(semver.New("4.0.0-rc").Compare(*semver.New("4.0.0-rc.2")), check.Equals, -1) 142 c.Assert(semver.New("4.0.0-rc.1").Compare(*semver.New("4.0.0-rc.2")), check.Equals, -1) 143 c.Assert(semver.New(removeVAndHash("4.0.0-rc-35-g31dae220")).Compare(*semver.New("4.0.0-rc.2")), check.Equals, -1) 144 c.Assert(semver.New(removeVAndHash("4.0.0-9-g30f0b014")).Compare(*semver.New("4.0.0-rc.1")), check.Equals, 1) 145 146 c.Assert(semver.New(removeVAndHash("4.0.0-rc-35-g31dae220")).Compare(*semver.New("4.0.0-rc.2")), check.Equals, -1) 147 c.Assert(semver.New(removeVAndHash("4.0.0-9-g30f0b014")).Compare(*semver.New("4.0.0-rc.1")), check.Equals, 1) 148 c.Assert(semver.New(removeVAndHash("v3.0.0-beta-211-g09beefbe0-dirty")). 149 Compare(*semver.New("3.0.0-beta")), check.Equals, 0) 150 c.Assert(semver.New(removeVAndHash("v3.0.5-dirty")). 151 Compare(*semver.New("3.0.5")), check.Equals, 0) 152 c.Assert(semver.New(removeVAndHash("v3.0.5-beta.12-dirty")). 153 Compare(*semver.New("3.0.5-beta.12")), check.Equals, 0) 154 c.Assert(semver.New(removeVAndHash("v2.1.0-rc.1-7-g38c939f-dirty")). 155 Compare(*semver.New("2.1.0-rc.1")), check.Equals, 0) 156 } 157 158 func (s *checkSuite) TestReleaseSemver(c *check.C) { 159 defer testleak.AfterTest(c)() 160 cases := []struct{ releaseVersion, releaseSemver string }{ 161 {"None", ""}, 162 {"HEAD", ""}, 163 {"v4.0.5", "4.0.5"}, 164 {"v4.0.2-152-g62d7075-dev", "4.0.2"}, 165 } 166 167 for _, cs := range cases { 168 ReleaseVersion = cs.releaseVersion 169 c.Assert(ReleaseSemver(), check.Equals, cs.releaseSemver, check.Commentf("%v", cs)) 170 } 171 } 172 173 func (s *checkSuite) TestGetTiCDCClusterVersion(c *check.C) { 174 defer testleak.AfterTest(c)() 175 testCases := []struct { 176 captureInfos []*model.CaptureInfo 177 expected TiCDCClusterVersion 178 }{ 179 { 180 captureInfos: []*model.CaptureInfo{}, 181 expected: TiCDCClusterVersionUnknown, 182 }, 183 { 184 captureInfos: []*model.CaptureInfo{ 185 {ID: "capture1", Version: ""}, 186 {ID: "capture2", Version: ""}, 187 {ID: "capture3", Version: ""}, 188 }, 189 expected: TiCDCClusterVersion{MinTiCDCVersion, false}, 190 }, 191 { 192 captureInfos: []*model.CaptureInfo{ 193 {ID: "capture1", Version: "5.0.1"}, 194 {ID: "capture2", Version: "4.0.7"}, 195 {ID: "capture3", Version: "5.0.0-rc"}, 196 }, 197 expected: TiCDCClusterVersion{semver.New("4.0.7"), false}, 198 }, 199 { 200 captureInfos: []*model.CaptureInfo{ 201 {ID: "capture1", Version: "5.0.0-rc"}, 202 }, 203 expected: TiCDCClusterVersion{semver.New("5.0.0-rc"), false}, 204 }, 205 { 206 captureInfos: []*model.CaptureInfo{ 207 {ID: "capture1", Version: "5.0.0"}, 208 }, 209 expected: TiCDCClusterVersion{semver.New("5.0.0"), false}, 210 }, 211 { 212 captureInfos: []*model.CaptureInfo{ 213 {ID: "capture1", Version: "4.1.0"}, 214 }, 215 expected: TiCDCClusterVersion{semver.New("4.1.0"), false}, 216 }, 217 { 218 captureInfos: []*model.CaptureInfo{ 219 {ID: "capture1", Version: "4.0.10"}, 220 }, 221 expected: TiCDCClusterVersion{semver.New("4.0.10"), false}, 222 }, 223 } 224 for _, tc := range testCases { 225 ver, err := GetTiCDCClusterVersion(tc.captureInfos) 226 c.Assert(err, check.IsNil) 227 c.Assert(ver, check.DeepEquals, tc.expected) 228 } 229 } 230 231 func (s *checkSuite) TestTiCDCClusterVersionFeaturesCompatible(c *check.C) { 232 defer testleak.AfterTest(c)() 233 234 ver := TiCDCClusterVersion{semver.New("4.0.10"), false} 235 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, false) 236 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, false) 237 238 ver = TiCDCClusterVersion{semver.New("4.0.12"), false} 239 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, false) 240 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, false) 241 242 ver = TiCDCClusterVersion{semver.New("4.0.13"), false} 243 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 244 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, false) 245 246 ver = TiCDCClusterVersion{semver.New("4.0.13-hotfix"), false} 247 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 248 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, false) 249 250 ver = TiCDCClusterVersion{semver.New("4.0.14"), false} 251 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 252 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, false) 253 254 ver = TiCDCClusterVersion{semver.New("5.0.0-rc"), false} 255 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, false) 256 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, true) 257 258 ver = TiCDCClusterVersion{semver.New("5.0.0"), false} 259 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 260 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, true) 261 262 ver = TiCDCClusterVersion{semver.New("5.1.0"), false} 263 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 264 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, true) 265 266 ver = TiCDCClusterVersion{semver.New("5.2.0-alpha"), false} 267 c.Assert(ver.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 268 c.Assert(ver.ShouldEnableOldValueByDefault(), check.Equals, true) 269 270 c.Assert(TiCDCClusterVersionUnknown.ShouldEnableUnifiedSorterByDefault(), check.Equals, true) 271 c.Assert(TiCDCClusterVersionUnknown.ShouldEnableOldValueByDefault(), check.Equals, true) 272 }