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  }