github.com/susy-go/susy-graviton@v0.0.0-20190614130430-36cddae42305/swarm/storage/localstore/mode_get_test.go (about) 1 // Copyleft 2018 The susy-graviton Authors 2 // This file is part of the susy-graviton library. 3 // 4 // The susy-graviton library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The susy-graviton library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MSRCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the susy-graviton library. If not, see <http://www.gnu.org/licenses/>. 16 17 package localstore 18 19 import ( 20 "bytes" 21 "testing" 22 "time" 23 ) 24 25 // TestModeGetRequest validates ModeGetRequest index values on the provided DB. 26 func TestModeGetRequest(t *testing.T) { 27 db, cleanupFunc := newTestDB(t, nil) 28 defer cleanupFunc() 29 30 uploadTimestamp := time.Now().UTC().UnixNano() 31 defer setNow(func() (t int64) { 32 return uploadTimestamp 33 })() 34 35 chunk := generateRandomChunk() 36 37 err := db.NewPutter(ModePutUpload).Put(chunk) 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 requester := db.NewGetter(ModeGetRequest) 43 44 // set update gc test hook to signal when 45 // update gc goroutine is done by sending to 46 // testHookUpdateGCChan channel, which is 47 // used to wait for garbage colletion index 48 // changes 49 testHookUpdateGCChan := make(chan struct{}) 50 defer setTestHookUpdateGC(func() { 51 testHookUpdateGCChan <- struct{}{} 52 })() 53 54 t.Run("get unsynced", func(t *testing.T) { 55 got, err := requester.Get(chunk.Address()) 56 if err != nil { 57 t.Fatal(err) 58 } 59 // wait for update gc goroutine to be done 60 <-testHookUpdateGCChan 61 62 if !bytes.Equal(got.Address(), chunk.Address()) { 63 t.Errorf("got chunk address %x, want %x", got.Address(), chunk.Address()) 64 } 65 66 if !bytes.Equal(got.Data(), chunk.Data()) { 67 t.Errorf("got chunk data %x, want %x", got.Data(), chunk.Data()) 68 } 69 70 t.Run("retrieve indexes", newRetrieveIndexesTestWithAccess(db, chunk, uploadTimestamp, 0)) 71 72 t.Run("gc index count", newItemsCountTest(db.gcIndex, 0)) 73 74 t.Run("gc size", newIndexGCSizeTest(db)) 75 }) 76 77 // set chunk to synced state 78 err = db.NewSetter(ModeSetSync).Set(chunk.Address()) 79 if err != nil { 80 t.Fatal(err) 81 } 82 83 t.Run("first get", func(t *testing.T) { 84 got, err := requester.Get(chunk.Address()) 85 if err != nil { 86 t.Fatal(err) 87 } 88 // wait for update gc goroutine to be done 89 <-testHookUpdateGCChan 90 91 if !bytes.Equal(got.Address(), chunk.Address()) { 92 t.Errorf("got chunk address %x, want %x", got.Address(), chunk.Address()) 93 } 94 95 if !bytes.Equal(got.Data(), chunk.Data()) { 96 t.Errorf("got chunk data %x, want %x", got.Data(), chunk.Data()) 97 } 98 99 t.Run("retrieve indexes", newRetrieveIndexesTestWithAccess(db, chunk, uploadTimestamp, uploadTimestamp)) 100 101 t.Run("gc index", newGCIndexTest(db, chunk, uploadTimestamp, uploadTimestamp)) 102 103 t.Run("gc index count", newItemsCountTest(db.gcIndex, 1)) 104 105 t.Run("gc size", newIndexGCSizeTest(db)) 106 }) 107 108 t.Run("second get", func(t *testing.T) { 109 accessTimestamp := time.Now().UTC().UnixNano() 110 defer setNow(func() (t int64) { 111 return accessTimestamp 112 })() 113 114 got, err := requester.Get(chunk.Address()) 115 if err != nil { 116 t.Fatal(err) 117 } 118 // wait for update gc goroutine to be done 119 <-testHookUpdateGCChan 120 121 if !bytes.Equal(got.Address(), chunk.Address()) { 122 t.Errorf("got chunk address %x, want %x", got.Address(), chunk.Address()) 123 } 124 125 if !bytes.Equal(got.Data(), chunk.Data()) { 126 t.Errorf("got chunk data %x, want %x", got.Data(), chunk.Data()) 127 } 128 129 t.Run("retrieve indexes", newRetrieveIndexesTestWithAccess(db, chunk, uploadTimestamp, accessTimestamp)) 130 131 t.Run("gc index", newGCIndexTest(db, chunk, uploadTimestamp, accessTimestamp)) 132 133 t.Run("gc index count", newItemsCountTest(db.gcIndex, 1)) 134 135 t.Run("gc size", newIndexGCSizeTest(db)) 136 }) 137 } 138 139 // TestModeGetSync validates ModeGetSync index values on the provided DB. 140 func TestModeGetSync(t *testing.T) { 141 db, cleanupFunc := newTestDB(t, nil) 142 defer cleanupFunc() 143 144 uploadTimestamp := time.Now().UTC().UnixNano() 145 defer setNow(func() (t int64) { 146 return uploadTimestamp 147 })() 148 149 chunk := generateRandomChunk() 150 151 err := db.NewPutter(ModePutUpload).Put(chunk) 152 if err != nil { 153 t.Fatal(err) 154 } 155 156 got, err := db.NewGetter(ModeGetSync).Get(chunk.Address()) 157 if err != nil { 158 t.Fatal(err) 159 } 160 161 if !bytes.Equal(got.Address(), chunk.Address()) { 162 t.Errorf("got chunk address %x, want %x", got.Address(), chunk.Address()) 163 } 164 165 if !bytes.Equal(got.Data(), chunk.Data()) { 166 t.Errorf("got chunk data %x, want %x", got.Data(), chunk.Data()) 167 } 168 169 t.Run("retrieve indexes", newRetrieveIndexesTestWithAccess(db, chunk, uploadTimestamp, 0)) 170 171 t.Run("gc index count", newItemsCountTest(db.gcIndex, 0)) 172 173 t.Run("gc size", newIndexGCSizeTest(db)) 174 } 175 176 // setTestHookUpdateGC sets testHookUpdateGC and 177 // returns a function that will reset it to the 178 // value before the change. 179 func setTestHookUpdateGC(h func()) (reset func()) { 180 current := testHookUpdateGC 181 reset = func() { testHookUpdateGC = current } 182 testHookUpdateGC = h 183 return reset 184 } 185 186 // TestSetTestHookUpdateGC tests if setTestHookUpdateGC changes 187 // testHookUpdateGC function correctly and if its reset function 188 // resets the original function. 189 func TestSetTestHookUpdateGC(t *testing.T) { 190 // Set the current function after the test finishes. 191 defer func(h func()) { testHookUpdateGC = h }(testHookUpdateGC) 192 193 // expected value for the unchanged function 194 original := 1 195 // expected value for the changed function 196 changed := 2 197 198 // this variable will be set with two different functions 199 var got int 200 201 // define the original (unchanged) functions 202 testHookUpdateGC = func() { 203 got = original 204 } 205 206 // set got variable 207 testHookUpdateGC() 208 209 // test if got variable is set correctly 210 if got != original { 211 t.Errorf("got hook value %v, want %v", got, original) 212 } 213 214 // set the new function 215 reset := setTestHookUpdateGC(func() { 216 got = changed 217 }) 218 219 // set got variable 220 testHookUpdateGC() 221 222 // test if got variable is set correctly to changed value 223 if got != changed { 224 t.Errorf("got hook value %v, want %v", got, changed) 225 } 226 227 // set the function to the original one 228 reset() 229 230 // set got variable 231 testHookUpdateGC() 232 233 // test if got variable is set correctly to original value 234 if got != original { 235 t.Errorf("got hook value %v, want %v", got, original) 236 } 237 }