gitlab.com/SkynetLabs/skyd@v1.6.9/skymodules/renter/skylink_test.go (about) 1 package renter 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 "time" 8 9 "gitlab.com/NebulousLabs/errors" 10 "gitlab.com/NebulousLabs/fastrand" 11 "gitlab.com/SkynetLabs/skyd/skymodules" 12 "go.sia.tech/siad/crypto" 13 ) 14 15 const ( 16 testSkylink1 = "AABEKWZ_wc2R9qlhYkzbG8mImFVi08kBu1nsvvwPLBtpEg" 17 testSkylink2 = "AADxpqE6bH2yFBuCFakOeouCj99CIIKSfgv4B9XsImkxLQ" 18 ) 19 20 var ( 21 skylink1 skymodules.Skylink 22 skylink2 skymodules.Skylink 23 ) 24 25 // TestSkylink probes the skylink manager subsystem. 26 func TestSkylink(t *testing.T) { 27 t.Parallel() 28 29 // Load Skylinks for tests 30 err := skylink1.LoadString(testSkylink1) 31 if err != nil { 32 t.Fatal(err) 33 } 34 err = skylink2.LoadString(testSkylink2) 35 if err != nil { 36 t.Fatal(err) 37 } 38 39 // Run Tests 40 t.Run("Basic", testSkylinkBasic) 41 t.Run("IsUnpinned", testIsUnpinned) 42 } 43 44 // testIsUnpinned probes the handling of checking if a filenode is considered 45 // unpinned. 46 func testIsUnpinned(t *testing.T) { 47 if testing.Short() { 48 t.SkipNow() 49 } 50 51 // Create renter 52 rt, err := newRenterTester(t.Name()) 53 if err != nil { 54 t.Fatal(err) 55 } 56 defer func() { 57 err = rt.Close() 58 if err != nil { 59 t.Fatal(err) 60 } 61 }() 62 63 // create siafile 64 sf, err := rt.renter.newRenterTestFile() 65 if err != nil { 66 t.Fatal(err) 67 } 68 defer func() { 69 err = sf.Close() 70 if err != nil { 71 t.Fatal(err) 72 } 73 }() 74 75 // add link to siafile 76 err = sf.AddSkylink(skylink1) 77 if err != nil { 78 t.Fatal(err) 79 } 80 81 // check isunpinned 82 if rt.renter.staticSkylinkManager.callIsUnpinned(sf) { 83 t.Error("filenode should not be considered unpinned") 84 } 85 86 // add different link to skylink manager 87 rt.renter.staticSkylinkManager.managedAddUnpinRequest(skylink2) 88 89 // check inunpinned 90 if rt.renter.staticSkylinkManager.callIsUnpinned(sf) { 91 t.Error("filenode should not be considered unpinned") 92 } 93 94 // add link to skylink manager 95 rt.renter.staticSkylinkManager.managedAddUnpinRequest(skylink1) 96 97 // check isunpinned 98 if !rt.renter.staticSkylinkManager.callIsUnpinned(sf) { 99 t.Error("filenode should be considered unpinned") 100 } 101 } 102 103 // testSkylinkBasic probes the basic functionality of the skylinkManager 104 func testSkylinkBasic(t *testing.T) { 105 // Initialize new skylinkManager 106 sm := newSkylinkManager() 107 start := time.Now() 108 109 // Calling prune on a newly initialized empty skylinkManager should be fine 110 sm.callPruneUnpinRequests() 111 112 // Add skylink 113 sm.managedAddUnpinRequest(skylink1) 114 115 // Define a helper to verify state. This basic test will be adding 1 skylink 116 // at a time and we want to make sure that the time is set to be far enough in 117 // the future. 118 verifyState := func(skylink skymodules.Skylink) error { 119 sm.mu.Lock() 120 defer sm.mu.Unlock() 121 if len(sm.unpinRequests) != 1 { 122 return fmt.Errorf("Prune result unexpected; have %v expected %v", len(sm.unpinRequests), 1) 123 } 124 urt, ok := sm.unpinRequests[skylink.String()] 125 if !ok { 126 return errors.New("skylink not in unpinRequests") 127 } 128 if urt.Before(start.Add(2 * TargetHealthCheckFrequency)) { 129 return errors.New("time not far enough in the future") 130 } 131 return nil 132 } 133 134 // Verify state 135 err := verifyState(skylink1) 136 if err != nil { 137 t.Fatal(err) 138 } 139 140 // Grab the unpinRequest time 141 sm.mu.Lock() 142 urt := sm.unpinRequests[skylink1.String()] 143 sm.mu.Unlock() 144 145 // Call prune, nothing should happen since the pruneTimeThreshold is still 0 146 // so no time is before it. 147 sm.callPruneUnpinRequests() 148 err = verifyState(skylink1) 149 if err != nil { 150 t.Fatal(err) 151 } 152 153 // Update the pruneTimeThreshold to now plus 2 * TargetHealthCheckFrequency. 154 // This will cause the first skylink to be pruned. 155 sm.callUpdatePruneTimeThreshold(time.Now().Add(2 * TargetHealthCheckFrequency)) 156 157 // Add skylink again should be a no-op 158 sm.managedAddUnpinRequest(skylink1) 159 err = verifyState(skylink1) 160 if err != nil { 161 t.Fatal(err) 162 } 163 sm.mu.Lock() 164 urt2 := sm.unpinRequests[skylink1.String()] 165 sm.mu.Unlock() 166 if !urt.Equal(urt2) { 167 t.Error("times shouldn't have been changed") 168 } 169 170 // Add a new skylink 171 sm.managedAddUnpinRequest(skylink2) 172 173 // Call prune, this should prune the original skylink and leave the new 174 // skylink. 175 sm.callPruneUnpinRequests() 176 177 // Only the last skylink should be in the unpinRequests 178 err = verifyState(skylink2) 179 if err != nil { 180 t.Fatal(err) 181 } 182 } 183 184 // TestBlocklistHash probes the BlocklistHash method of the renter. 185 func TestBlocklistHash(t *testing.T) { 186 if testing.Short() { 187 t.SkipNow() 188 } 189 t.Parallel() 190 191 // Create workertester 192 wt, err := newWorkerTester(t.Name()) 193 if err != nil { 194 t.Fatal(err) 195 } 196 defer func() { 197 err = wt.Close() 198 if err != nil { 199 t.Fatal(err) 200 } 201 }() 202 203 // Grab renter 204 r := wt.rt.renter 205 206 // Generate V1 Skylink 207 var mr crypto.Hash 208 fastrand.Read(mr[:]) 209 skylinkV1, err := skymodules.NewSkylinkV1(mr, 0, 0) 210 if err != nil { 211 t.Fatal(err) 212 } 213 214 // Check hash returned from V1 Skylinks 215 hash, err := r.managedBlocklistHash(context.Background(), skylinkV1, false) 216 if err != nil { 217 t.Fatal(err) 218 } 219 expected := crypto.HashObject(skylinkV1.MerkleRoot()) 220 if hash != expected { 221 t.Fatal("hashes not equal", hash, expected) 222 } 223 224 // Create a V2 link based on the the V1 link 225 // 226 // Update the registry with that link. 227 srv, spk, sk := randomRegistryValue() 228 srv.Data = skylinkV1.Bytes() 229 srv.Revision++ 230 srv = srv.Sign(sk) 231 err = wt.UpdateRegistry(context.Background(), spk, srv) 232 if err != nil { 233 t.Fatal(err) 234 } 235 236 // Get the v2 skylink. 237 skylinkV2 := skymodules.NewSkylinkV2(spk, srv.Tweak) 238 239 // Check V2 link created from V1 link to verify that it also returns the same hash 240 hash, err = r.managedBlocklistHash(context.Background(), skylinkV2, false) 241 if err != nil { 242 t.Fatal(err) 243 } 244 if hash != expected { 245 t.Fatal("hashes not equal", hash, expected) 246 } 247 }