github.com/decred/dcrlnd@v0.7.6/channeldb/reports_test.go (about) 1 package channeldb 2 3 import ( 4 "bytes" 5 "testing" 6 7 "github.com/decred/dcrd/chaincfg/chainhash" 8 "github.com/decred/dcrd/wire" 9 "github.com/decred/dcrlnd/kvdb" 10 "github.com/stretchr/testify/require" 11 ) 12 13 var ( 14 testChainHash = [chainhash.HashSize]byte{ 15 0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda, 16 0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17, 17 0x2d, 0xe7, 0x93, 0xe4, 18 } 19 20 testChanPoint1 = wire.OutPoint{ 21 Hash: chainhash.Hash{ 22 0x51, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda, 23 0x48, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17, 24 0x2d, 0xe7, 0x93, 0xe4, 25 }, 26 Index: 1, 27 } 28 ) 29 30 // TestPersistReport tests the writing and retrieval of a report on disk with 31 // and without a spend txid. 32 func TestPersistReport(t *testing.T) { 33 tests := []struct { 34 name string 35 spendTxID *chainhash.Hash 36 }{ 37 { 38 name: "Non-nil spend txid", 39 spendTxID: &testChanPoint1.Hash, 40 }, 41 { 42 name: "Nil spend txid", 43 spendTxID: nil, 44 }, 45 } 46 47 for _, test := range tests { 48 test := test 49 50 t.Run(test.name, func(t *testing.T) { 51 db, cleanup, err := MakeTestDB() 52 require.NoError(t, err) 53 defer cleanup() 54 55 channelOutpoint := testChanPoint1 56 57 testOutpoint := testChanPoint1 58 testOutpoint.Index++ 59 60 report := &ResolverReport{ 61 OutPoint: testOutpoint, 62 Amount: 2, 63 ResolverType: 1, 64 ResolverOutcome: 2, 65 SpendTxID: test.spendTxID, 66 } 67 68 // Write report to disk, and ensure it is identical when 69 // it is read. 70 err = db.PutResolverReport( 71 nil, testChainHash, &channelOutpoint, report, 72 ) 73 require.NoError(t, err) 74 75 reports, err := db.FetchChannelReports( 76 testChainHash, &channelOutpoint, 77 ) 78 require.NoError(t, err) 79 require.Equal(t, report, reports[0]) 80 }) 81 } 82 } 83 84 // TestFetchChannelReadBucket tests retrieval of the reports bucket for a 85 // channel, testing that the appropriate error is returned based on the state 86 // of the existing bucket. 87 func TestFetchChannelReadBucket(t *testing.T) { 88 db, cleanup, err := MakeTestDB() 89 require.NoError(t, err) 90 defer cleanup() 91 92 channelOutpoint := testChanPoint1 93 94 testOutpoint := testChanPoint1 95 testOutpoint.Index++ 96 97 // If we attempt to get reports when we do not have any present, we 98 // expect to fail because our chain hash bucket is not present. 99 _, err = db.FetchChannelReports( 100 testChainHash, &channelOutpoint, 101 ) 102 require.Equal(t, ErrNoChainHashBucket, err) 103 104 // Finally we write a report to disk and check that we can fetch it. 105 report := &ResolverReport{ 106 OutPoint: testOutpoint, 107 Amount: 2, 108 ResolverOutcome: 1, 109 ResolverType: 2, 110 SpendTxID: nil, 111 } 112 113 err = db.PutResolverReport( 114 nil, testChainHash, &channelOutpoint, report, 115 ) 116 require.NoError(t, err) 117 118 // Now that the channel bucket exists, we expect the channel to be 119 // successfully fetched, with no reports. 120 reports, err := db.FetchChannelReports(testChainHash, &testChanPoint1) 121 require.NoError(t, err) 122 require.Equal(t, report, reports[0]) 123 } 124 125 // TestFetchChannelWriteBucket tests the creation of missing buckets when 126 // retrieving the reports bucket. 127 func TestFetchChannelWriteBucket(t *testing.T) { 128 createReportsBucket := func(tx kvdb.RwTx) (kvdb.RwBucket, error) { 129 return tx.CreateTopLevelBucket(closedChannelBucket) 130 } 131 132 createChainHashBucket := func(reports kvdb.RwBucket) (kvdb.RwBucket, 133 error) { 134 135 return reports.CreateBucketIfNotExists(testChainHash[:]) 136 } 137 138 createChannelBucket := func(chainHash kvdb.RwBucket) (kvdb.RwBucket, 139 error) { 140 141 var chanPointBuf bytes.Buffer 142 err := writeOutpoint(&chanPointBuf, &testChanPoint1) 143 require.NoError(t, err) 144 145 return chainHash.CreateBucketIfNotExists(chanPointBuf.Bytes()) 146 } 147 148 tests := []struct { 149 name string 150 setup func(tx kvdb.RwTx) error 151 }{ 152 { 153 name: "no existing buckets", 154 setup: func(tx kvdb.RwTx) error { 155 return nil 156 }, 157 }, 158 { 159 name: "reports bucket exists", 160 setup: func(tx kvdb.RwTx) error { 161 _, err := createReportsBucket(tx) 162 return err 163 }, 164 }, 165 { 166 name: "chainhash bucket exists", 167 setup: func(tx kvdb.RwTx) error { 168 reports, err := createReportsBucket(tx) 169 if err != nil { 170 return err 171 } 172 173 _, err = createChainHashBucket(reports) 174 return err 175 }, 176 }, 177 { 178 name: "channel bucket exists", 179 setup: func(tx kvdb.RwTx) error { 180 reports, err := createReportsBucket(tx) 181 if err != nil { 182 return err 183 } 184 185 chainHash, err := createChainHashBucket(reports) 186 if err != nil { 187 return err 188 } 189 190 _, err = createChannelBucket(chainHash) 191 return err 192 }, 193 }, 194 } 195 196 for _, test := range tests { 197 test := test 198 199 t.Run(test.name, func(t *testing.T) { 200 db, cleanup, err := MakeTestDB() 201 require.NoError(t, err) 202 defer cleanup() 203 204 // Update our db to the starting state we expect. 205 err = kvdb.Update(db, test.setup, func() {}) 206 require.NoError(t, err) 207 208 // Try to get our report bucket. 209 err = kvdb.Update(db, func(tx kvdb.RwTx) error { 210 _, err := fetchReportWriteBucket( 211 tx, testChainHash, &testChanPoint1, 212 ) 213 return err 214 }, func() {}) 215 require.NoError(t, err) 216 }) 217 } 218 }