lab.nexedi.com/kirr/go123@v0.0.0-20240207185015-8299741fa871/xnet/lonet/registry_sqlite_test.go (about) 1 // Copyright (C) 2018 Nexedi SA and Contributors. 2 // Kirill Smelkov <kirr@nexedi.com> 3 // 4 // This program is free software: you can Use, Study, Modify and Redistribute 5 // it under the terms of the GNU General Public License version 3, or (at your 6 // option) any later version, as published by the Free Software Foundation. 7 // 8 // You can also Link and Combine this program with other software covered by 9 // the terms of any of the Free Software licenses or any of the Open Source 10 // Initiative approved licenses and Convey the resulting work. Corresponding 11 // source of such a combination shall include the source code for all other 12 // software used. 13 // 14 // This program is distributed WITHOUT ANY WARRANTY; without even the implied 15 // warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16 // 17 // See COPYING file for full licensing terms. 18 // See https://www.nexedi.com/licensing for rationale and options. 19 20 package lonet 21 22 import ( 23 "context" 24 "fmt" 25 "testing" 26 27 "lab.nexedi.com/kirr/go123/exc" 28 "lab.nexedi.com/kirr/go123/xnet/virtnet" 29 ) 30 31 // registryTester is handy utility to test sqliteRegistry 32 type registryTester struct { 33 *testing.T 34 r *sqliteRegistry 35 } 36 37 // Query checks that result of Query(hostname) is as expected. 38 // 39 // if expect is error - it checks that Query returns error with cause == expect. 40 // otherwise expect must be string and it will check that Query 41 // succeeds and returns osladdr == expect. 42 func (t *registryTester) Query(hostname string, expect interface{}) { 43 t.Helper() 44 r := t.r 45 46 osladdr, err := r.Query(context.Background(), hostname) 47 if ewant, iserr := expect.(error); iserr { 48 // error expected 49 // XXX construct full registry error around ewant + reflect.DeepCompare? 50 e, ok := err.(*virtnet.RegistryError) 51 if !(ok && e.Err == ewant && osladdr == "") { 52 t.Fatalf("%s: query %q:\nwant: \"\", %v\nhave: %q, %v", 53 r.uri, hostname, ewant, osladdr, err) 54 } 55 } else { 56 // !error expected 57 laddr := expect.(string) 58 if !(osladdr == laddr && err == nil) { 59 t.Fatalf("%s: query %q:\nwant: %q, nil\nhave: %q, %v", 60 r.uri, hostname, laddr, osladdr, err) 61 } 62 } 63 } 64 65 // Announce checks that result of Announce(hostname, osladdr) is as expected. 66 // 67 // if len(errv) == 1 - it checks that Announce returns error with cause == errv[0]. 68 // otherwise it will check that Announce succeeds and returns nil error. 69 func (t *registryTester) Announce(hostname, osladdr string, errv ...error) { 70 t.Helper() 71 r := t.r 72 73 err := r.Announce(context.Background(), hostname, osladdr) 74 var ewant error 75 if len(errv) > 0 { 76 ewant = errv[0] 77 if len(errv) > 1 { 78 panic("only 1 error allowed in announce check") 79 } 80 } 81 if ewant != nil { 82 // error expected 83 // XXX construct full registry error around ewant + reflect.DeepCompare? 84 e, ok := err.(*virtnet.RegistryError) 85 if (!ok && e.Err == ewant) { 86 t.Fatalf("%s: announce %q %q:\nwant %v\nhave: %v", 87 r.uri, hostname, osladdr, ewant, err) 88 } 89 } else { 90 // !error expected 91 if err != nil { 92 t.Fatalf("%s: announce %q %q: %s", r.uri, hostname, osladdr, err) 93 } 94 } 95 } 96 97 // handy shortcuts for registry errors, ... 98 var ø = virtnet.ErrNoHost 99 var DUP = virtnet.ErrHostDup 100 var RDOWN = virtnet.ErrRegistryDown 101 102 var X = exc.Raiseif 103 var bg = context.Background() 104 105 106 func TestRegistrySQLite(t *testing.T) { 107 work := xworkdir(t) 108 dbpath := work + "/1.db" 109 110 r1, err := openRegistrySQLite(bg, dbpath, "aaa") 111 X(err) 112 113 t1 := ®istryTester{t, r1} 114 t1.Query("α", ø) 115 t1.Announce("α", "alpha:1234") 116 t1.Announce("α", "alpha:1234", DUP) 117 t1.Announce("α", "alpha:1235", DUP) 118 t1.Query("α", "alpha:1234") 119 t1.Query("β", ø) 120 121 r2, err := openRegistrySQLite(bg, dbpath, "aaa") 122 X(err) 123 124 t2 := ®istryTester{t, r2} 125 t2.Query("α", "alpha:1234") 126 t2.Query("β", ø) 127 t2.Announce("β", "beta:zzz") 128 t2.Query("β", "beta:zzz") 129 130 t1.Query("β", "beta:zzz") 131 132 X(r1.Close()) 133 134 t1.Query("α", RDOWN) 135 t1.Query("β", RDOWN) 136 t1.Announce("γ", "gamma:qqq", RDOWN) 137 t1.Query("γ", RDOWN) 138 139 t2.Query("α", "alpha:1234") 140 141 X(r2.Close()) 142 143 t2.Query("α", RDOWN) 144 145 146 // verify network mismatch detection works 147 r3, err := openRegistrySQLite(bg, dbpath, "bbb") 148 if !(r3 == nil && err != nil) { 149 t.Fatalf("network mismatch: not detected") 150 } 151 errWant := fmt.Sprintf(`%s: open []: setup "bbb": network name mismatch: want "bbb"; have "aaa"`, dbpath) 152 if err.Error() != errWant { 153 t.Fatalf("network mismatch: error:\nhave: %q\nwant: %q", err.Error(), errWant) 154 } 155 } 156 157 158 // verify that go and python implementations of sqlite registry understand each other. 159 func TestRegistrySQLitePyGo(t *testing.T) { 160 needPy(t) 161 162 work := xworkdir(t) 163 dbpath := work + "/1.db" 164 165 r1, err := openRegistrySQLite(bg, dbpath, "ccc") 166 X(err) 167 168 t1 := ®istryTester{t, r1} 169 t1.Query("α", ø) 170 t1.Announce("α", "alpha:1234") 171 t1.Announce("α", "alpha:1234", DUP) 172 t1.Announce("α", "alpha:1235", DUP) 173 t1.Query("α", "alpha:1234") 174 t1.Query("β", ø) 175 176 // in python: check/modify the registry 177 err = pytest("-k", "test_registry_pygo", "--registry-dbpath", dbpath, "lonet_test.py") 178 X(err) 179 180 // back in go: python must have set β + α should stay the same 181 t1.Query("β", "beta:py") 182 t1.Query("α", "alpha:1234") 183 }