decred.org/dcrdex@v1.0.5/client/db/test/dbtest.go (about) 1 // This code is available on the terms of the project LICENSE.md file, 2 // also available online at https://blueoakcouncil.org/license/1.0.0. 3 4 package dbtest 5 6 import ( 7 "bytes" 8 "math/rand" 9 "strings" 10 "time" 11 12 "decred.org/dcrdex/client/asset" 13 "decred.org/dcrdex/client/db" 14 ordertest "decred.org/dcrdex/dex/order/test" 15 "github.com/decred/dcrd/dcrec/secp256k1/v4" 16 ) 17 18 func init() { 19 rand.Seed(time.Now().UnixNano()) 20 } 21 22 // Generate a public key on the secp256k1 curve. 23 func randomPubKey() *secp256k1.PublicKey { 24 //return secp256k1.NewPublicKey(secp256k1.S256().ScalarBaseMult(randBytes(32))) 25 priv, err := secp256k1.GeneratePrivateKey() 26 if err != nil { 27 panic(err.Error()) 28 } 29 return priv.PubKey() 30 } 31 32 func randString(maxLen int) string { 33 s := string(randBytes(int(randBytes(1)[0]))) 34 if len(s) > maxLen { 35 s = s[:maxLen] 36 } 37 return s 38 } 39 40 // RandomAccountInfo creates an AccountInfo with random values. 41 func RandomAccountInfo() *db.AccountInfo { 42 return &db.AccountInfo{ 43 Host: ordertest.RandomAddress(), 44 // LegacyEncKey: randBytes(32), 45 EncKeyV2: randBytes(32), 46 DEXPubKey: randomPubKey(), 47 TargetTier: uint64(rand.Intn(34)), 48 MaxBondedAmt: uint64(rand.Intn(40e8)), 49 BondAsset: uint32(rand.Intn(66)), 50 LegacyFeeAssetID: uint32(rand.Intn(64)), 51 LegacyFeeCoin: randBytes(32), 52 Cert: randBytes(100), 53 } 54 } 55 56 // RandomBalance creates a random balance. 57 func RandomBalance() *asset.Balance { 58 return &asset.Balance{ 59 Available: rand.Uint64(), 60 Immature: rand.Uint64(), 61 Locked: rand.Uint64(), 62 } 63 } 64 65 func RandomPrimaryCredentials() *db.PrimaryCredentials { 66 return &db.PrimaryCredentials{ 67 EncSeed: randBytes(10), 68 EncInnerKey: randBytes(10), 69 InnerKeyParams: randBytes(10), 70 OuterKeyParams: randBytes(10), 71 Birthday: time.Unix(rand.Int63(), 0), 72 Version: 1, 73 } 74 } 75 76 // RandomWallet creates a random wallet. 77 func RandomWallet() *db.Wallet { 78 return &db.Wallet{ 79 AssetID: rand.Uint32(), 80 Settings: map[string]string{ 81 ordertest.RandomAddress(): ordertest.RandomAddress(), 82 ordertest.RandomAddress(): ordertest.RandomAddress(), 83 ordertest.RandomAddress(): ordertest.RandomAddress(), 84 ordertest.RandomAddress(): ordertest.RandomAddress(), 85 }, 86 Balance: &db.Balance{ 87 Balance: *RandomBalance(), 88 Stamp: time.Unix(rand.Int63()/(1<<31), 0), 89 }, 90 Address: ordertest.RandomAddress(), 91 } 92 } 93 94 func randBytes(l int) []byte { 95 b := make([]byte, l) 96 rand.Read(b) 97 return b 98 } 99 100 // RandomMatchProof creates a match proof with random values. Set the sparsity 101 // to change how many fields are populated, with some variation around the ratio 102 // supplied. 0 < sparsity < 1. 103 func RandomMatchProof(sparsity float64) *db.MatchProof { 104 proof := new(db.MatchProof) 105 doZero := func() bool { return rand.Intn(1000) < int(sparsity*1000) } 106 if !doZero() { 107 proof.CounterContract = randBytes(75) 108 } 109 if !doZero() { 110 proof.CounterTxData = randBytes(20) 111 } 112 if !doZero() { 113 proof.SecretHash = randBytes(32) 114 } 115 if !doZero() { 116 proof.Secret = randBytes(32) 117 } 118 if !doZero() { 119 proof.MakerSwap = randBytes(36) 120 } 121 if !doZero() { 122 proof.MakerRedeem = randBytes(36) 123 } 124 if !doZero() { 125 proof.TakerSwap = randBytes(36) 126 } 127 if !doZero() { 128 proof.TakerRedeem = randBytes(36) 129 } 130 if !doZero() { 131 proof.Auth.MatchSig = randBytes(73) 132 } 133 if !doZero() { 134 proof.Auth.MatchStamp = rand.Uint64() 135 } 136 if !doZero() { 137 proof.Auth.InitSig = randBytes(73) 138 } 139 if !doZero() { 140 proof.Auth.InitStamp = rand.Uint64() 141 } 142 if !doZero() { 143 proof.Auth.AuditSig = randBytes(73) 144 } 145 if !doZero() { 146 proof.Auth.AuditStamp = rand.Uint64() 147 } 148 if !doZero() { 149 proof.Auth.RedeemSig = randBytes(73) 150 } 151 if !doZero() { 152 proof.Auth.RedeemStamp = rand.Uint64() 153 } 154 if !doZero() { 155 proof.Auth.RedemptionSig = randBytes(73) 156 } 157 if !doZero() { 158 proof.Auth.RedemptionStamp = rand.Uint64() 159 } 160 return proof 161 } 162 163 func RandomNotification(maxTime uint64) *db.Notification { 164 return &db.Notification{ 165 NoteType: ordertest.RandomAddress(), 166 SubjectText: ordertest.RandomAddress(), 167 DetailText: ordertest.RandomAddress(), 168 // Since this is for DB tests, only use severity level >= Success. 169 Severeness: db.Severity(rand.Intn(3)) + db.Success, 170 TimeStamp: uint64(rand.Int63n(int64(maxTime))), 171 } 172 } 173 174 type testKiller interface { 175 Helper() 176 Fatalf(string, ...any) 177 } 178 179 // MustCompareMatchAuth ensures the two MatchAuth are identical, calling the 180 // Fatalf method of the testKiller if not. 181 func MustCompareMatchAuth(t testKiller, a1, a2 *db.MatchAuth) { 182 if !bytes.Equal(a1.MatchSig, a2.MatchSig) { 183 t.Fatalf("MatchSig mismatch. %x != %x", a1.MatchSig, a2.MatchSig) 184 } 185 if a1.MatchStamp != a2.MatchStamp { 186 t.Fatalf("MatchStamp mismatch. %d != %d", a1.MatchStamp, a2.MatchStamp) 187 } 188 if !bytes.Equal(a1.InitSig, a2.InitSig) { 189 t.Fatalf("InitSig mismatch. %x != %x", a1.InitSig, a2.InitSig) 190 } 191 if a1.InitStamp != a2.InitStamp { 192 t.Fatalf("InitStamp mismatch. %d != %d", a1.InitStamp, a2.InitStamp) 193 } 194 if !bytes.Equal(a1.AuditSig, a2.AuditSig) { 195 t.Fatalf("AuditSig mismatch. %x != %x", a1.AuditSig, a2.AuditSig) 196 } 197 if a1.AuditStamp != a2.AuditStamp { 198 t.Fatalf("AuditStamp mismatch. %d != %d", a1.AuditStamp, a2.AuditStamp) 199 } 200 if !bytes.Equal(a1.RedeemSig, a2.RedeemSig) { 201 t.Fatalf("RedeemSig mismatch. %x != %x", a1.RedeemSig, a2.RedeemSig) 202 } 203 if a1.RedeemStamp != a2.RedeemStamp { 204 t.Fatalf("RedeemStamp mismatch. %d != %d", a1.RedeemStamp, a2.RedeemStamp) 205 } 206 if !bytes.Equal(a1.RedemptionSig, a2.RedemptionSig) { 207 t.Fatalf("RedemptionSig mismatch. %x != %x", a1.RedemptionSig, a2.RedemptionSig) 208 } 209 if a1.RedemptionStamp != a2.RedemptionStamp { 210 t.Fatalf("RedemptionStamp mismatch. %d != %d", a1.RedemptionStamp, a2.RedemptionStamp) 211 } 212 } 213 214 // MustCompareMatchMetaData ensure the two MatchMetaData are identical, calling 215 // the Fatalf method of the testKiller if not. 216 func MustCompareMatchMetaData(t testKiller, m1, m2 *db.MatchMetaData) { 217 if m1.DEX != m2.DEX { 218 t.Fatalf("DEX mismatch. %d != %d", m1.DEX, m2.DEX) 219 } 220 if m1.Base != m2.Base { 221 t.Fatalf("Base mismatch. %d != %d", m1.Base, m2.Base) 222 } 223 if m1.Quote != m2.Quote { 224 t.Fatalf("Quote mismatch. %d != %d", m1.Quote, m2.Quote) 225 } 226 if m1.Stamp != m2.Stamp { 227 t.Fatalf("Stamp mismatch. %d != %d", m1.Stamp, m2.Stamp) 228 } 229 MustCompareMatchProof(t, &m1.Proof, &m2.Proof) 230 } 231 232 // MustCompareMatchProof ensures the two MatchProof are identical, calling the 233 // Fatalf method of the testKiller if not. 234 func MustCompareMatchProof(t testKiller, m1, m2 *db.MatchProof) { 235 if !bytes.Equal(m1.CounterContract, m2.CounterContract) { 236 t.Fatalf("CounterContract mismatch. %x != %x", m1.CounterContract, m2.CounterContract) 237 } 238 if !bytes.Equal(m1.CounterTxData, m2.CounterTxData) { 239 t.Fatalf("CounterTxData mismatch. %x != %x", m1.CounterTxData, m2.CounterTxData) 240 } 241 if !bytes.Equal(m1.SecretHash, m2.SecretHash) { 242 t.Fatalf("SecretHash mismatch. %x != %x", m1.SecretHash, m2.SecretHash) 243 } 244 if !bytes.Equal(m1.Secret, m2.Secret) { 245 t.Fatalf("SecretKey mismatch. %x != %x", m1.Secret, m2.Secret) 246 } 247 if !bytes.Equal(m1.MakerSwap, m2.MakerSwap) { 248 t.Fatalf("MakerSwap mismatch. %x != %x", m1.MakerSwap, m2.MakerSwap) 249 } 250 if !bytes.Equal(m1.MakerRedeem, m2.MakerRedeem) { 251 t.Fatalf("MakerRedeem mismatch. %x != %x", m1.MakerRedeem, m2.MakerRedeem) 252 } 253 if !bytes.Equal(m1.TakerSwap, m2.TakerSwap) { 254 t.Fatalf("TakerSwap mismatch. %x != %x", m1.TakerSwap, m2.TakerSwap) 255 } 256 if !bytes.Equal(m1.TakerRedeem, m2.TakerRedeem) { 257 t.Fatalf("TakerRedeem mismatch. %x != %x", m1.TakerRedeem, m2.TakerRedeem) 258 } 259 MustCompareMatchAuth(t, &m1.Auth, &m2.Auth) 260 } 261 262 // MustCompareAccountInfo ensures the two AccountInfo are identical, calling the 263 // Fatalf method of the testKiller if not. 264 func MustCompareAccountInfo(t testKiller, a1, a2 *db.AccountInfo) { 265 t.Helper() 266 if a1.Host != a2.Host { 267 t.Fatalf("Host mismatch. %s != %s", a1.Host, a2.Host) 268 } 269 if !bytes.Equal(a1.LegacyEncKey, a2.LegacyEncKey) { 270 t.Fatalf("LegacyEncKey mismatch. %x != %x", a1.LegacyEncKey, a2.LegacyEncKey) 271 } 272 if !bytes.Equal(a1.EncKeyV2, a2.EncKeyV2) { 273 t.Fatalf("EncKeyV2 mismatch. %x != %x", a1.EncKeyV2, a2.EncKeyV2) 274 } 275 if !bytes.Equal(a1.DEXPubKey.SerializeCompressed(), a2.DEXPubKey.SerializeCompressed()) { 276 t.Fatalf("EncKey mismatch. %x != %x", 277 a1.DEXPubKey.SerializeCompressed(), a2.DEXPubKey.SerializeCompressed()) 278 } 279 if !bytes.Equal(a1.LegacyFeeCoin, a2.LegacyFeeCoin) { 280 t.Fatalf("EncKey mismatch. %x != %x", a1.LegacyFeeCoin, a2.LegacyFeeCoin) 281 } 282 } 283 284 // MustCompareOrderProof ensures the two OrderProof are identical, calling the 285 // Fatalf method of the testKiller if not. 286 func MustCompareOrderProof(t testKiller, p1, p2 *db.OrderProof) { 287 if !bytes.Equal(p1.DEXSig, p2.DEXSig) { 288 t.Fatalf("DEXSig mismatch. %x != %x", p1.DEXSig, p2.DEXSig) 289 } 290 if !bytes.Equal(p1.Preimage, p2.Preimage) { 291 t.Fatalf("Preimage mismatch. %x != %x", p1.Preimage, p2.Preimage) 292 } 293 } 294 295 // MustCompareWallets ensures the two Wallet are identical, calling the Fatalf 296 // method of the testKiller if not. 297 func MustCompareWallets(t testKiller, w1, w2 *db.Wallet) { 298 if w1.AssetID != w2.AssetID { 299 t.Fatalf("AssetID mismatch. %d != %d", w1.AssetID, w2.AssetID) 300 } 301 if len(w1.Settings) != len(w2.Settings) { 302 t.Fatalf("Settings mismatch. %d != %s", len(w1.Settings), len(w2.Settings)) 303 } 304 w2Settings := make(map[string]string, len(w2.Settings)) 305 for k, v := range w2.Settings { 306 w2Settings[strings.ToLower(k)] = v 307 } 308 for k, v1 := range w1.Settings { 309 if v2, ok := w2Settings[k]; !ok { 310 t.Fatalf("Settings mismatch: key '%s' not found in one wallet", k) 311 } else if v1 != v2 { 312 t.Fatalf("Settings mismatch: different values for key '%s'", k) 313 } 314 } 315 MustCompareBalances(t, w1.Balance, w2.Balance) 316 if w1.Address != w2.Address { 317 t.Fatalf("Address mismatch. %s != %s", w1.Address, w2.Address) 318 } 319 if !bytes.Equal(w1.EncryptedPW, w2.EncryptedPW) { 320 t.Fatalf("EncryptedPW mismatch. %x != %x", w1.EncryptedPW, w2.EncryptedPW) 321 } 322 } 323 324 // MustCompareBalances ensures the two BalanceSet are identical, calling the 325 // Fatalf method of the testKiller if not. 326 func MustCompareBalances(t testKiller, b1, b2 *db.Balance) { 327 if !b1.Stamp.Equal(b2.Stamp) { 328 t.Fatalf("balance timestamp mismatch. %s != %s", b1.Stamp, b2.Stamp) 329 } 330 MustCompareAssetBalances(t, "zero-conf", &b1.Balance, &b2.Balance) 331 } 332 333 // MustCompareAssetBalances ensures the two asset.Balances are identical, 334 // calling the Fatalf method of the testKiller if not. 335 func MustCompareAssetBalances(t testKiller, host string, b1, b2 *asset.Balance) { 336 if b1.Available != b2.Available { 337 t.Fatalf("%s available balance mismatch. %d != %d", host, b1.Available, b2.Available) 338 } 339 if b1.Immature != b2.Immature { 340 t.Fatalf("%s immature balance mismatch. %d != %d", host, b1.Immature, b2.Immature) 341 } 342 if b1.Locked != b2.Locked { 343 t.Fatalf("%s locked balance mismatch. %d != %d", host, b1.Locked, b2.Locked) 344 } 345 } 346 347 func MustCompareNotifications(t testKiller, n1, n2 *db.Notification) { 348 if n1.NoteType != n2.NoteType { 349 t.Fatalf("NoteType mismatch. %s != %s", n1.NoteType, n2.NoteType) 350 } 351 if n1.SubjectText != n2.SubjectText { 352 t.Fatalf("SubjectText mismatch. %s != %s", n1.SubjectText, n2.SubjectText) 353 } 354 if n1.DetailText != n2.DetailText { 355 t.Fatalf("DetailText mismatch. %s != %s", n1.DetailText, n2.DetailText) 356 } 357 if n1.Severeness != n2.Severeness { 358 t.Fatalf("Severeness mismatch. %d != %d", n1.Severeness, n2.Severeness) 359 } 360 if n1.TimeStamp != n2.TimeStamp { 361 t.Fatalf("TimeStamp mismatch. %d != %d", n1.TimeStamp, n2.TimeStamp) 362 } 363 if n1.ID().String() != n2.ID().String() { 364 t.Fatalf("ID mismatch. %s != %s", n1.ID(), n2.ID()) 365 } 366 }