github.com/braveheart12/just@v0.8.7/ledger/artifactmanager/artifactmanager_test.go (about) 1 /* 2 * Copyright 2019 Insolar Technologies 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package artifactmanager 18 19 import ( 20 "context" 21 "math/rand" 22 "testing" 23 24 "github.com/gojuno/minimock" 25 "github.com/insolar/insolar/ledger/storage/nodes" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 "github.com/stretchr/testify/suite" 29 30 "github.com/insolar/insolar/component" 31 "github.com/insolar/insolar/configuration" 32 "github.com/insolar/insolar/core" 33 "github.com/insolar/insolar/core/delegationtoken" 34 "github.com/insolar/insolar/core/message" 35 "github.com/insolar/insolar/core/reply" 36 "github.com/insolar/insolar/instrumentation/inslogger" 37 "github.com/insolar/insolar/ledger/recentstorage" 38 "github.com/insolar/insolar/ledger/storage" 39 "github.com/insolar/insolar/ledger/storage/index" 40 "github.com/insolar/insolar/ledger/storage/jet" 41 "github.com/insolar/insolar/ledger/storage/record" 42 "github.com/insolar/insolar/ledger/storage/storagetest" 43 "github.com/insolar/insolar/platformpolicy" 44 "github.com/insolar/insolar/testutils" 45 "github.com/insolar/insolar/testutils/testmessagebus" 46 ) 47 48 type amSuite struct { 49 suite.Suite 50 51 cm *component.Manager 52 ctx context.Context 53 cleaner func() 54 db storage.DBContext 55 56 scheme core.PlatformCryptographyScheme 57 pulseTracker storage.PulseTracker 58 nodeStorage nodes.Accessor 59 objectStorage storage.ObjectStorage 60 jetStorage storage.JetStorage 61 dropStorage storage.DropStorage 62 genesisState storage.GenesisState 63 } 64 65 func NewAmSuite() *amSuite { 66 return &amSuite{ 67 Suite: suite.Suite{}, 68 } 69 } 70 71 // Init and run suite 72 func TestArtifactManager(t *testing.T) { 73 suite.Run(t, NewAmSuite()) 74 } 75 76 func (s *amSuite) BeforeTest(suiteName, testName string) { 77 s.cm = &component.Manager{} 78 s.ctx = inslogger.TestContext(s.T()) 79 80 db, cleaner := storagetest.TmpDB(s.ctx, s.T()) 81 s.cleaner = cleaner 82 s.db = db 83 s.scheme = platformpolicy.NewPlatformCryptographyScheme() 84 s.jetStorage = storage.NewJetStorage() 85 s.nodeStorage = nodes.NewStorage() 86 s.pulseTracker = storage.NewPulseTracker() 87 s.objectStorage = storage.NewObjectStorage() 88 s.dropStorage = storage.NewDropStorage(10) 89 s.genesisState = storage.NewGenesisInitializer() 90 91 s.cm.Inject( 92 s.scheme, 93 s.db, 94 s.jetStorage, 95 s.nodeStorage, 96 s.pulseTracker, 97 s.objectStorage, 98 s.dropStorage, 99 s.genesisState, 100 ) 101 102 err := s.cm.Init(s.ctx) 103 if err != nil { 104 s.T().Error("ComponentManager init failed", err) 105 } 106 err = s.cm.Start(s.ctx) 107 if err != nil { 108 s.T().Error("ComponentManager start failed", err) 109 } 110 } 111 112 func (s *amSuite) AfterTest(suiteName, testName string) { 113 err := s.cm.Stop(s.ctx) 114 if err != nil { 115 s.T().Error("ComponentManager stop failed", err) 116 } 117 s.cleaner() 118 } 119 120 var ( 121 domainID = *genRandomID(0) 122 domainRef = *core.NewRecordRef(domainID, domainID) 123 requestRef = *genRandomRef(0) 124 ) 125 126 func genRandomID(pulse core.PulseNumber) *core.RecordID { 127 buff := [core.RecordIDSize - core.PulseNumberSize]byte{} 128 _, err := rand.Read(buff[:]) 129 if err != nil { 130 panic(err) 131 } 132 return core.NewRecordID(pulse, buff[:]) 133 } 134 135 func genRefWithID(id *core.RecordID) *core.RecordRef { 136 return core.NewRecordRef(domainID, *id) 137 } 138 139 func genRandomRef(pulse core.PulseNumber) *core.RecordRef { 140 return genRefWithID(genRandomID(pulse)) 141 } 142 143 func getTestData(s *amSuite) ( 144 context.Context, 145 storage.ObjectStorage, 146 *LedgerArtifactManager, 147 ) { 148 mc := minimock.NewController(s.T()) 149 pulseStorage := storage.NewPulseStorage() 150 pulseStorage.PulseTracker = s.pulseTracker 151 152 pulse, err := s.pulseTracker.GetLatestPulse(s.ctx) 153 require.NoError(s.T(), err) 154 pulseStorage.Set(&pulse.Pulse) 155 156 mb := testmessagebus.NewTestMessageBus(s.T()) 157 mb.PulseStorage = pulseStorage 158 159 certificate := testutils.NewCertificateMock(s.T()) 160 certificate.GetRoleMock.Return(core.StaticRoleLightMaterial) 161 162 handler := MessageHandler{ 163 replayHandlers: map[core.MessageType]core.MessageHandler{}, 164 PlatformCryptographyScheme: s.scheme, 165 conf: &configuration.Ledger{LightChainLimit: 3, PendingRequestsLimit: 10}, 166 certificate: certificate, 167 } 168 169 handler.Nodes = s.nodeStorage 170 handler.ObjectStorage = s.objectStorage 171 handler.PulseTracker = s.pulseTracker 172 handler.DBContext = s.db 173 handler.JetStorage = s.jetStorage 174 175 indexMock := recentstorage.NewRecentIndexStorageMock(s.T()) 176 pendingMock := recentstorage.NewPendingStorageMock(s.T()) 177 178 indexMock.AddObjectMock.Return() 179 pendingMock.GetRequestsForObjectMock.Return(nil) 180 pendingMock.AddPendingRequestMock.Return() 181 pendingMock.RemovePendingRequestMock.Return() 182 183 provideMock := recentstorage.NewProviderMock(s.T()) 184 provideMock.GetIndexStorageMock.Return(indexMock) 185 provideMock.GetPendingStorageMock.Return(pendingMock) 186 provideMock.CountMock.Return(1) 187 188 handler.RecentStorageProvider = provideMock 189 190 handler.Bus = mb 191 192 jc := testutils.NewJetCoordinatorMock(mc) 193 jc.LightExecutorForJetMock.Return(&core.RecordRef{}, nil) 194 jc.MeMock.Return(core.RecordRef{}) 195 jc.HeavyMock.Return(&core.RecordRef{}, nil) 196 jc.NodeForJetMock.Return(&core.RecordRef{}, nil) 197 jc.IsBeyondLimitMock.Return(false, nil) 198 199 handler.JetCoordinator = jc 200 201 err = handler.Init(s.ctx) 202 require.NoError(s.T(), err) 203 204 am := LedgerArtifactManager{ 205 DB: s.db, 206 DefaultBus: mb, 207 getChildrenChunkSize: 100, 208 PlatformCryptographyScheme: s.scheme, 209 PulseStorage: pulseStorage, 210 GenesisState: s.genesisState, 211 } 212 213 return s.ctx, s.objectStorage, &am 214 } 215 216 func (s *amSuite) TestLedgerArtifactManager_RegisterRequest() { 217 ctx, os, am := getTestData(s) 218 219 parcel := message.Parcel{Msg: &message.GenesisRequest{Name: "4K3NiGuqYGqKPnYp6XeGd2kdN4P9veL6rYcWkLKWXZCu.4FFB8zfQoGznSmzDxwv4njX1aR9ioL8GHSH17QXH2AFa"}} 220 id, err := am.RegisterRequest(ctx, *am.GenesisRef(), &parcel) 221 assert.NoError(s.T(), err) 222 rec, err := os.GetRecord(ctx, *jet.NewID(0, nil), id) 223 assert.NoError(s.T(), err) 224 225 assert.Equal( 226 s.T(), 227 am.PlatformCryptographyScheme.IntegrityHasher().Hash(message.MustSerializeBytes(parcel.Msg)), 228 rec.(*record.RequestRecord).MessageHash, 229 ) 230 } 231 232 func (s *amSuite) TestLedgerArtifactManager_GetCodeWithCache() { 233 code := []byte("test_code") 234 codeRef := testutils.RandomRef() 235 236 mb := testutils.NewMessageBusMock(s.T()) 237 mb.SendFunc = func(p context.Context, p1 core.Message, p3 *core.MessageSendOptions) (r core.Reply, r1 error) { 238 return &reply.Code{ 239 Code: code, 240 }, nil 241 } 242 243 jc := testutils.NewJetCoordinatorMock(s.T()) 244 jc.LightExecutorForJetMock.Return(&core.RecordRef{}, nil) 245 jc.MeMock.Return(core.RecordRef{}) 246 247 amPulseStorageMock := testutils.NewPulseStorageMock(s.T()) 248 amPulseStorageMock.CurrentFunc = func(p context.Context) (r *core.Pulse, r1 error) { 249 pulse, err := s.pulseTracker.GetLatestPulse(p) 250 require.NoError(s.T(), err) 251 return &pulse.Pulse, err 252 } 253 254 am := LedgerArtifactManager{ 255 DefaultBus: mb, 256 DB: s.db, 257 PulseStorage: amPulseStorageMock, 258 JetCoordinator: jc, 259 PlatformCryptographyScheme: s.scheme, 260 senders: newLedgerArtifactSenders(), 261 } 262 263 desc, err := am.GetCode(s.ctx, codeRef) 264 receivedCode, err := desc.Code() 265 require.NoError(s.T(), err) 266 require.Equal(s.T(), code, receivedCode) 267 268 mb.SendFunc = func(p context.Context, p1 core.Message, p3 *core.MessageSendOptions) (r core.Reply, r1 error) { 269 s.T().Fatal("Func must not be called here") 270 return nil, nil 271 } 272 273 desc, err = am.GetCode(s.ctx, codeRef) 274 receivedCode, err = desc.Code() 275 require.NoError(s.T(), err) 276 require.Equal(s.T(), code, receivedCode) 277 278 } 279 280 func (s *amSuite) TestLedgerArtifactManager_DeclareType() { 281 ctx, os, am := getTestData(s) 282 283 typeDec := []byte{1, 2, 3} 284 id, err := am.DeclareType(ctx, domainRef, requestRef, typeDec) 285 assert.NoError(s.T(), err) 286 typeRec, err := os.GetRecord(ctx, *jet.NewID(0, nil), id) 287 assert.NoError(s.T(), err) 288 assert.Equal(s.T(), &record.TypeRecord{ 289 SideEffectRecord: record.SideEffectRecord{ 290 Domain: domainRef, 291 Request: requestRef, 292 }, 293 TypeDeclaration: typeDec, 294 }, typeRec) 295 } 296 297 func (s *amSuite) TestLedgerArtifactManager_DeployCode_CreatesCorrectRecord() { 298 ctx, os, am := getTestData(s) 299 300 id, err := am.DeployCode( 301 ctx, 302 domainRef, 303 requestRef, 304 []byte{1, 2, 3}, 305 core.MachineTypeBuiltin, 306 ) 307 assert.NoError(s.T(), err) 308 codeRec, err := os.GetRecord(ctx, *jet.NewID(0, nil), id) 309 assert.NoError(s.T(), err) 310 assert.Equal(s.T(), codeRec, &record.CodeRecord{ 311 SideEffectRecord: record.SideEffectRecord{ 312 Domain: domainRef, 313 Request: requestRef, 314 }, 315 Code: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{1, 2, 3}), 316 MachineType: core.MachineTypeBuiltin, 317 }) 318 } 319 320 func (s *amSuite) TestLedgerArtifactManager_ActivateObject_CreatesCorrectRecord() { 321 ctx, os, am := getTestData(s) 322 jetID := *jet.NewID(0, nil) 323 324 memory := []byte{1, 2, 3} 325 codeRef := genRandomRef(0) 326 parentID, _ := os.SetRecord( 327 ctx, 328 jetID, 329 core.GenesisPulse.PulseNumber, 330 &record.ObjectActivateRecord{ 331 SideEffectRecord: record.SideEffectRecord{ 332 Domain: *genRandomRef(0), 333 }, 334 }, 335 ) 336 err := os.SetObjectIndex(ctx, jetID, parentID, &index.ObjectLifeline{ 337 LatestState: parentID, 338 }) 339 require.NoError(s.T(), err) 340 341 objRef := *genRandomRef(0) 342 objDesc, err := am.ActivateObject( 343 ctx, 344 domainRef, 345 objRef, 346 *genRefWithID(parentID), 347 *codeRef, 348 false, 349 memory, 350 ) 351 assert.Nil(s.T(), err) 352 activateRec, err := os.GetRecord(ctx, jetID, objDesc.StateID()) 353 assert.Nil(s.T(), err) 354 assert.Equal(s.T(), activateRec, &record.ObjectActivateRecord{ 355 SideEffectRecord: record.SideEffectRecord{ 356 Domain: domainRef, 357 Request: objRef, 358 }, 359 ObjectStateRecord: record.ObjectStateRecord{ 360 Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, memory), 361 Image: *codeRef, 362 IsPrototype: false, 363 }, 364 Parent: *genRefWithID(parentID), 365 IsDelegate: false, 366 }) 367 368 idx, err := os.GetObjectIndex(ctx, jetID, parentID, false) 369 assert.NoError(s.T(), err) 370 childRec, err := os.GetRecord(ctx, jetID, idx.ChildPointer) 371 assert.NoError(s.T(), err) 372 assert.Equal(s.T(), objRef, childRec.(*record.ChildRecord).Ref) 373 374 idx, err = os.GetObjectIndex(ctx, jetID, objRef.Record(), false) 375 assert.NoError(s.T(), err) 376 assert.Equal(s.T(), *objDesc.StateID(), *idx.LatestState) 377 assert.Equal(s.T(), *objDesc.Parent(), idx.Parent) 378 } 379 380 func (s *amSuite) TestLedgerArtifactManager_DeactivateObject_CreatesCorrectRecord() { 381 ctx, os, am := getTestData(s) 382 jetID := *jet.NewID(0, nil) 383 384 objID, _ := os.SetRecord( 385 ctx, 386 jetID, 387 core.GenesisPulse.PulseNumber, 388 &record.ObjectActivateRecord{ 389 SideEffectRecord: record.SideEffectRecord{ 390 Domain: *genRandomRef(0), 391 }, 392 }, 393 ) 394 err := os.SetObjectIndex(ctx, jetID, objID, &index.ObjectLifeline{ 395 State: record.StateActivation, 396 LatestState: objID, 397 }) 398 require.NoError(s.T(), err) 399 deactivateID, err := am.DeactivateObject( 400 ctx, 401 domainRef, 402 requestRef, 403 &ObjectDescriptor{ 404 ctx: ctx, 405 head: *genRefWithID(objID), 406 state: *objID, 407 }, 408 ) 409 assert.Nil(s.T(), err) 410 deactivateRec, err := os.GetRecord(ctx, jetID, deactivateID) 411 assert.Nil(s.T(), err) 412 assert.Equal(s.T(), deactivateRec, &record.DeactivationRecord{ 413 SideEffectRecord: record.SideEffectRecord{ 414 Domain: domainRef, 415 Request: requestRef, 416 }, 417 PrevState: *objID, 418 }) 419 } 420 421 func (s *amSuite) TestLedgerArtifactManager_UpdateObject_CreatesCorrectRecord() { 422 ctx, os, am := getTestData(s) 423 jetID := *jet.NewID(0, nil) 424 425 objID, _ := os.SetRecord( 426 ctx, 427 jetID, 428 core.GenesisPulse.PulseNumber, 429 &record.ObjectActivateRecord{ 430 SideEffectRecord: record.SideEffectRecord{ 431 Domain: *genRandomRef(0), 432 }, 433 }, 434 ) 435 err := os.SetObjectIndex(ctx, jetID, objID, &index.ObjectLifeline{ 436 State: record.StateActivation, 437 LatestState: objID, 438 }) 439 require.NoError(s.T(), err) 440 memory := []byte{1, 2, 3} 441 prototype := genRandomRef(0) 442 obj, err := am.UpdateObject( 443 ctx, 444 domainRef, 445 requestRef, 446 &ObjectDescriptor{ 447 ctx: ctx, 448 head: *genRefWithID(objID), 449 state: *objID, 450 prototype: prototype, 451 }, 452 memory, 453 ) 454 assert.Nil(s.T(), err) 455 updateRec, err := os.GetRecord(ctx, jetID, obj.StateID()) 456 assert.Nil(s.T(), err) 457 assert.Equal(s.T(), updateRec, &record.ObjectAmendRecord{ 458 SideEffectRecord: record.SideEffectRecord{ 459 Domain: domainRef, 460 Request: requestRef, 461 }, 462 ObjectStateRecord: record.ObjectStateRecord{ 463 Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, memory), 464 Image: *prototype, 465 IsPrototype: false, 466 }, 467 PrevState: *objID, 468 }) 469 } 470 471 func (s *amSuite) TestLedgerArtifactManager_GetObject_ReturnsCorrectDescriptors() { 472 ctx, os, am := getTestData(s) 473 jetID := *jet.NewID(0, nil) 474 475 prototypeRef := genRandomRef(0) 476 parentRef := genRandomRef(0) 477 objRef := genRandomRef(0) 478 _, err := os.SetRecord( 479 ctx, 480 jetID, 481 core.GenesisPulse.PulseNumber, 482 &record.ObjectActivateRecord{ 483 SideEffectRecord: record.SideEffectRecord{ 484 Domain: domainRef, 485 }, 486 ObjectStateRecord: record.ObjectStateRecord{ 487 Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{3}), 488 }, 489 Parent: *parentRef, 490 }, 491 ) 492 require.NoError(s.T(), err) 493 _, err = os.SetBlob(ctx, jetID, core.GenesisPulse.PulseNumber, []byte{3}) 494 require.NoError(s.T(), err) 495 objectAmendID, _ := os.SetRecord(ctx, jetID, core.GenesisPulse.PulseNumber, &record.ObjectAmendRecord{ 496 SideEffectRecord: record.SideEffectRecord{ 497 Domain: domainRef, 498 }, 499 ObjectStateRecord: record.ObjectStateRecord{ 500 Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{4}), 501 Image: *prototypeRef, 502 }, 503 }) 504 _, err = os.SetBlob(ctx, jetID, core.GenesisPulse.PulseNumber, []byte{4}) 505 require.NoError(s.T(), err) 506 507 objectIndex := index.ObjectLifeline{ 508 LatestState: objectAmendID, 509 ChildPointer: genRandomID(0), 510 Parent: *parentRef, 511 } 512 require.NoError( 513 s.T(), 514 os.SetObjectIndex(ctx, jetID, objRef.Record(), &objectIndex), 515 ) 516 517 objDesc, err := am.GetObject(ctx, *objRef, nil, false) 518 rObjDesc := objDesc.(*ObjectDescriptor) 519 assert.NoError(s.T(), err) 520 expectedObjDesc := &ObjectDescriptor{ 521 ctx: rObjDesc.ctx, 522 am: am, 523 head: *objRef, 524 state: *objectAmendID, 525 prototype: prototypeRef, 526 isPrototype: false, 527 childPointer: objectIndex.ChildPointer, 528 memory: []byte{4}, 529 parent: *parentRef, 530 } 531 assert.Equal(s.T(), *expectedObjDesc, *rObjDesc) 532 } 533 534 func (s *amSuite) TestLedgerArtifactManager_GetObject_FollowsRedirect() { 535 mc := minimock.NewController(s.T()) 536 am := NewArtifactManger() 537 mb := testutils.NewMessageBusMock(mc) 538 539 objRef := genRandomRef(0) 540 nodeRef := genRandomRef(0) 541 mb.SendFunc = func(c context.Context, m core.Message, o *core.MessageSendOptions) (r core.Reply, r1 error) { 542 o = o.Safe() 543 544 switch m.(type) { 545 case *message.GetObjectIndex: 546 return &reply.ObjectIndex{}, nil 547 case *message.GetObject: 548 if o.Receiver == nil { 549 return &reply.GetObjectRedirectReply{ 550 Receiver: nodeRef, 551 Token: &delegationtoken.GetObjectRedirectToken{Signature: []byte{1, 2, 3}}, 552 }, nil 553 } 554 555 token, ok := o.Token.(*delegationtoken.GetObjectRedirectToken) 556 assert.True(s.T(), ok) 557 assert.Equal(s.T(), []byte{1, 2, 3}, token.Signature) 558 assert.Equal(s.T(), nodeRef, o.Receiver) 559 return &reply.Object{}, nil 560 default: 561 panic("unexpected call") 562 } 563 } 564 am.DefaultBus = mb 565 am.DB = s.db 566 am.PulseStorage = makePulseStorage(s) 567 568 _, err := am.GetObject(s.ctx, *objRef, nil, false) 569 570 require.NoError(s.T(), err) 571 } 572 573 func (s *amSuite) TestLedgerArtifactManager_GetChildren() { 574 // t.Parallel() 575 ctx, os, am := getTestData(s) 576 // defer cleaner() 577 jetID := *jet.NewID(0, nil) 578 579 parentID, _ := os.SetRecord( 580 ctx, 581 jetID, 582 core.GenesisPulse.PulseNumber, 583 &record.ObjectActivateRecord{ 584 SideEffectRecord: record.SideEffectRecord{ 585 Domain: domainRef, 586 }, 587 ObjectStateRecord: record.ObjectStateRecord{ 588 Memory: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{0}), 589 }, 590 }) 591 child1Ref := genRandomRef(1) 592 child2Ref := genRandomRef(1) 593 child3Ref := genRandomRef(2) 594 595 childMeta1, _ := os.SetRecord( 596 ctx, 597 jetID, 598 core.GenesisPulse.PulseNumber, 599 &record.ChildRecord{ 600 Ref: *child1Ref, 601 }) 602 childMeta2, _ := os.SetRecord( 603 ctx, 604 jetID, 605 core.GenesisPulse.PulseNumber, 606 &record.ChildRecord{ 607 PrevChild: childMeta1, 608 Ref: *child2Ref, 609 }) 610 childMeta3, _ := os.SetRecord( 611 ctx, 612 jetID, 613 core.GenesisPulse.PulseNumber, 614 &record.ChildRecord{ 615 PrevChild: childMeta2, 616 Ref: *child3Ref, 617 }) 618 619 parentIndex := index.ObjectLifeline{ 620 LatestState: parentID, 621 ChildPointer: childMeta3, 622 } 623 require.NoError( 624 s.T(), 625 os.SetObjectIndex(ctx, jetID, parentID, &parentIndex), 626 ) 627 628 s.T().Run("returns correct children without pulse", func(t *testing.T) { 629 i, err := am.GetChildren(ctx, *genRefWithID(parentID), nil) 630 require.NoError(t, err) 631 child, err := i.Next() 632 assert.NoError(t, err) 633 assert.Equal(t, *child3Ref, *child) 634 child, err = i.Next() 635 assert.NoError(t, err) 636 assert.Equal(t, *child2Ref, *child) 637 child, err = i.Next() 638 assert.NoError(t, err) 639 assert.Equal(t, *child1Ref, *child) 640 hasNext := i.HasNext() 641 assert.False(t, hasNext) 642 _, err = i.Next() 643 assert.Error(t, err) 644 }) 645 646 s.T().Run("returns correct children with pulse", func(t *testing.T) { 647 pn := core.PulseNumber(1) 648 i, err := am.GetChildren(ctx, *genRefWithID(parentID), &pn) 649 require.NoError(t, err) 650 child, err := i.Next() 651 assert.NoError(t, err) 652 assert.Equal(t, *child2Ref, *child) 653 child, err = i.Next() 654 assert.NoError(t, err) 655 assert.Equal(t, *child1Ref, *child) 656 hasNext := i.HasNext() 657 assert.NoError(t, err) 658 assert.False(t, hasNext) 659 _, err = i.Next() 660 assert.Error(t, err) 661 }) 662 663 s.T().Run("returns correct children in many chunks", func(t *testing.T) { 664 am.getChildrenChunkSize = 1 665 i, err := am.GetChildren(ctx, *genRefWithID(parentID), nil) 666 require.NoError(t, err) 667 child, err := i.Next() 668 assert.NoError(t, err) 669 assert.Equal(t, *child3Ref, *child) 670 child, err = i.Next() 671 assert.NoError(t, err) 672 assert.Equal(t, *child2Ref, *child) 673 child, err = i.Next() 674 assert.NoError(t, err) 675 assert.Equal(t, *child1Ref, *child) 676 hasNext := i.HasNext() 677 assert.NoError(t, err) 678 assert.False(t, hasNext) 679 _, err = i.Next() 680 assert.Error(t, err) 681 }) 682 683 s.T().Run("doesn't fail when has no children to return", func(t *testing.T) { 684 am.getChildrenChunkSize = 1 685 pn := core.PulseNumber(3) 686 i, err := am.GetChildren(ctx, *genRefWithID(parentID), &pn) 687 require.NoError(t, err) 688 child, err := i.Next() 689 assert.NoError(t, err) 690 assert.Equal(t, *child3Ref, *child) 691 child, err = i.Next() 692 assert.NoError(t, err) 693 assert.Equal(t, *child2Ref, *child) 694 child, err = i.Next() 695 assert.NoError(t, err) 696 assert.Equal(t, *child1Ref, *child) 697 hasNext := i.HasNext() 698 assert.NoError(t, err) 699 assert.False(t, hasNext) 700 _, err = i.Next() 701 assert.Error(t, err) 702 }) 703 } 704 705 func makePulseStorage(s *amSuite) core.PulseStorage { 706 pulseStorage := storage.NewPulseStorage() 707 pulseStorage.PulseTracker = s.pulseTracker 708 pulse, err := s.pulseTracker.GetLatestPulse(s.ctx) 709 require.NoError(s.T(), err) 710 pulseStorage.Set(&pulse.Pulse) 711 712 return pulseStorage 713 } 714 715 func (s *amSuite) TestLedgerArtifactManager_GetChildren_FollowsRedirect() { 716 mc := minimock.NewController(s.T()) 717 am := NewArtifactManger() 718 mb := testutils.NewMessageBusMock(mc) 719 720 am.DB = s.db 721 am.PulseStorage = makePulseStorage(s) 722 723 objRef := genRandomRef(0) 724 nodeRef := genRandomRef(0) 725 mb.SendFunc = func(c context.Context, m core.Message, o *core.MessageSendOptions) (r core.Reply, r1 error) { 726 o = o.Safe() 727 if o.Receiver == nil { 728 return &reply.GetChildrenRedirectReply{ 729 Receiver: nodeRef, 730 Token: &delegationtoken.GetChildrenRedirectToken{Signature: []byte{1, 2, 3}}, 731 }, nil 732 } 733 734 token, ok := o.Token.(*delegationtoken.GetChildrenRedirectToken) 735 assert.True(s.T(), ok) 736 assert.Equal(s.T(), []byte{1, 2, 3}, token.Signature) 737 assert.Equal(s.T(), nodeRef, o.Receiver) 738 return &reply.Children{}, nil 739 } 740 am.DefaultBus = mb 741 742 _, err := am.GetChildren(s.ctx, *objRef, nil) 743 require.NoError(s.T(), err) 744 } 745 746 func (s *amSuite) TestLedgerArtifactManager_HandleJetDrop() { 747 s.T().Skip("jet drops are for validation and it doesn't work") 748 749 ctx, os, am := getTestData(s) 750 751 codeRecord := record.CodeRecord{ 752 Code: record.CalculateIDForBlob(am.PlatformCryptographyScheme, core.GenesisPulse.PulseNumber, []byte{1, 2, 3, 3, 2, 1}), 753 } 754 755 setRecordMessage := message.SetRecord{ 756 Record: record.SerializeRecord(&codeRecord), 757 } 758 759 jetID := *jet.NewID(0, nil) 760 761 rep, err := am.DefaultBus.Send(ctx, &message.JetDrop{ 762 JetID: jetID, 763 Messages: [][]byte{ 764 message.ToBytes(&setRecordMessage), 765 }, 766 PulseNumber: core.GenesisPulse.PulseNumber, 767 }, nil) 768 assert.NoError(s.T(), err) 769 assert.Equal(s.T(), reply.OK{}, *rep.(*reply.OK)) 770 771 id := record.NewRecordIDFromRecord(s.scheme, 0, &codeRecord) 772 rec, err := os.GetRecord(ctx, jetID, id) 773 require.NoError(s.T(), err) 774 assert.Equal(s.T(), codeRecord, *rec.(*record.CodeRecord)) 775 } 776 777 func (s *amSuite) TestLedgerArtifactManager_RegisterValidation() { 778 mc := minimock.NewController(s.T()) 779 defer mc.Finish() 780 781 mb := testmessagebus.NewTestMessageBus(s.T()) 782 mb.PulseStorage = makePulseStorage(s) 783 jc := testutils.NewJetCoordinatorMock(mc) 784 jc.IsBeyondLimitMock.Return(false, nil) 785 jc.NodeForJetMock.Return(&core.RecordRef{}, nil) 786 787 indexMock := recentstorage.NewRecentIndexStorageMock(s.T()) 788 pendingMock := recentstorage.NewPendingStorageMock(s.T()) 789 790 indexMock.AddObjectMock.Return() 791 pendingMock.GetRequestsForObjectMock.Return(nil) 792 pendingMock.AddPendingRequestMock.Return() 793 pendingMock.RemovePendingRequestMock.Return() 794 795 provideMock := recentstorage.NewProviderMock(s.T()) 796 provideMock.GetIndexStorageMock.Return(indexMock) 797 provideMock.GetPendingStorageMock.Return(pendingMock) 798 provideMock.CountMock.Return(0) 799 800 certificate := testutils.NewCertificateMock(s.T()) 801 certificate.GetRoleMock.Return(core.StaticRoleLightMaterial) 802 803 handler := MessageHandler{ 804 replayHandlers: map[core.MessageType]core.MessageHandler{}, 805 PlatformCryptographyScheme: s.scheme, 806 conf: &configuration.Ledger{LightChainLimit: 3, PendingRequestsLimit: 10}, 807 certificate: certificate, 808 } 809 810 handler.Bus = mb 811 handler.JetCoordinator = jc 812 handler.DBContext = s.db 813 handler.ObjectStorage = s.objectStorage 814 handler.PulseTracker = s.pulseTracker 815 handler.Nodes = s.nodeStorage 816 handler.JetStorage = s.jetStorage 817 818 handler.RecentStorageProvider = provideMock 819 820 err := handler.Init(s.ctx) 821 require.NoError(s.T(), err) 822 823 amPulseStorageMock := testutils.NewPulseStorageMock(s.T()) 824 amPulseStorageMock.CurrentFunc = func(p context.Context) (r *core.Pulse, r1 error) { 825 pulse, err := s.pulseTracker.GetLatestPulse(p) 826 require.NoError(s.T(), err) 827 return &pulse.Pulse, err 828 } 829 830 am := LedgerArtifactManager{ 831 DB: s.db, 832 DefaultBus: mb, 833 getChildrenChunkSize: 100, 834 PlatformCryptographyScheme: s.scheme, 835 PulseStorage: amPulseStorageMock, 836 GenesisState: s.genesisState, 837 } 838 839 objID, err := am.RegisterRequest( 840 s.ctx, 841 *am.GenesisRef(), 842 &message.Parcel{ 843 Msg: &message.GenesisRequest{ 844 Name: "4K3NiGuqYGqKPnYp6XeGd2kdN4P9veL6rYcWkLKWXZCu.4FFB8zfQoGznSmzDxwv4njX1aR9ioL8GHSH17QXH2AFa", 845 }, 846 }, 847 ) 848 require.NoError(s.T(), err) 849 objRef := genRefWithID(objID) 850 851 desc, err := am.ActivateObject( 852 s.ctx, 853 domainRef, 854 *objRef, 855 *am.GenesisRef(), 856 *genRandomRef(0), 857 false, 858 []byte{1}, 859 ) 860 require.NoError(s.T(), err) 861 stateID1 := desc.StateID() 862 863 desc, err = am.GetObject(s.ctx, *objRef, nil, false) 864 require.NoError(s.T(), err) 865 require.Equal(s.T(), *stateID1, *desc.StateID()) 866 867 _, err = am.GetObject(s.ctx, *objRef, nil, true) 868 require.Equal(s.T(), err, core.ErrStateNotAvailable) 869 870 desc, err = am.GetObject(s.ctx, *objRef, nil, false) 871 require.NoError(s.T(), err) 872 desc, err = am.UpdateObject( 873 s.ctx, 874 domainRef, 875 *genRandomRef(0), 876 desc, 877 []byte{3}, 878 ) 879 require.NoError(s.T(), err) 880 stateID3 := desc.StateID() 881 err = am.RegisterValidation(s.ctx, *objRef, *stateID1, true, nil) 882 require.NoError(s.T(), err) 883 884 desc, err = am.GetObject(s.ctx, *objRef, nil, false) 885 assert.NoError(s.T(), err) 886 assert.Equal(s.T(), *stateID3, *desc.StateID()) 887 desc, err = am.GetObject(s.ctx, *objRef, nil, true) 888 assert.NoError(s.T(), err) 889 assert.Equal(s.T(), *stateID1, *desc.StateID()) 890 } 891 892 func (s *amSuite) TestLedgerArtifactManager_RegisterResult() { 893 ctx, os, am := getTestData(s) 894 895 objID := core.RecordID{1, 2, 3} 896 request := genRandomRef(0) 897 requestID, err := am.RegisterResult(ctx, *core.NewRecordRef(core.RecordID{}, objID), *request, []byte{1, 2, 3}) 898 assert.NoError(s.T(), err) 899 900 rec, err := os.GetRecord(ctx, *jet.NewID(0, nil), requestID) 901 assert.NoError(s.T(), err) 902 assert.Equal(s.T(), record.ResultRecord{ 903 Object: objID, 904 Request: *request, 905 Payload: []byte{1, 2, 3}, 906 }, *rec.(*record.ResultRecord)) 907 } 908 909 func (s *amSuite) TestLedgerArtifactManager_RegisterRequest_JetMiss() { 910 mc := minimock.NewController(s.T()) 911 defer mc.Finish() 912 913 cs := platformpolicy.NewPlatformCryptographyScheme() 914 am := NewArtifactManger() 915 am.PlatformCryptographyScheme = cs 916 pulseStorageMock := testutils.NewPulseStorageMock(s.T()) 917 pulseStorageMock.CurrentFunc = func(ctx context.Context) (*core.Pulse, error) { 918 return &core.Pulse{PulseNumber: core.FirstPulseNumber}, nil 919 } 920 921 am.PulseStorage = pulseStorageMock 922 am.GenesisState = s.genesisState 923 am.JetStorage = s.jetStorage 924 925 s.T().Run("returns error on exceeding retry limit", func(t *testing.T) { 926 mb := testutils.NewMessageBusMock(mc) 927 am.DefaultBus = mb 928 mb.SendMock.Return(&reply.JetMiss{JetID: *jet.NewID(5, []byte{1, 2, 3}), Pulse: core.FirstPulseNumber}, nil) 929 _, err := am.RegisterRequest(s.ctx, *am.GenesisRef(), &message.Parcel{Msg: &message.CallMethod{}}) 930 require.Error(t, err) 931 }) 932 933 s.T().Run("returns no error and updates tree when jet miss", func(t *testing.T) { 934 mb := testutils.NewMessageBusMock(mc) 935 am.DefaultBus = mb 936 retries := 3 937 mb.SendFunc = func(c context.Context, m core.Message, o *core.MessageSendOptions) (r core.Reply, r1 error) { 938 if retries == 0 { 939 return &reply.ID{}, nil 940 } 941 retries-- 942 return &reply.JetMiss{JetID: *jet.NewID(4, []byte{0xD5}), Pulse: core.FirstPulseNumber}, nil 943 } 944 _, err := am.RegisterRequest(s.ctx, *am.GenesisRef(), &message.Parcel{Msg: &message.CallMethod{}}) 945 require.NoError(t, err) 946 947 jetID, actual := s.jetStorage.FindJet( 948 s.ctx, core.FirstPulseNumber, *core.NewRecordID(0, []byte{0xD5}), 949 ) 950 assert.Equal(t, *jet.NewID(4, []byte{0xD0}), *jetID) 951 assert.True(t, actual) 952 }) 953 } 954 955 func (s *amSuite) TestLedgerArtifactManager_GetRequest_Success() { 956 // Arrange 957 mc := minimock.NewController(s.T()) 958 defer mc.Finish() 959 objectID := testutils.RandomID() 960 requestID := testutils.RandomID() 961 962 node := testutils.RandomRef() 963 964 jc := testutils.NewJetCoordinatorMock(mc) 965 jc.NodeForObjectMock.Return(&node, nil) 966 967 pulseStorageMock := testutils.NewPulseStorageMock(mc) 968 pulseStorageMock.CurrentMock.Return(core.GenesisPulse, nil) 969 970 var parcel core.Parcel = &message.Parcel{PulseNumber: 123987} 971 resRecord := record.RequestRecord{ 972 Parcel: message.ParcelToBytes(parcel), 973 } 974 finalResponse := &reply.Request{Record: record.SerializeRecord(&resRecord)} 975 976 mb := testutils.NewMessageBusMock(s.T()) 977 mb.SendFunc = func(p context.Context, p1 core.Message, p2 *core.MessageSendOptions) (r core.Reply, r1 error) { 978 switch mb.SendCounter { 979 case 0: 980 casted, ok := p1.(*message.GetPendingRequestID) 981 require.Equal(s.T(), true, ok) 982 require.Equal(s.T(), objectID, casted.ObjectID) 983 return &reply.ID{ID: requestID}, nil 984 case 1: 985 casted, ok := p1.(*message.GetRequest) 986 require.Equal(s.T(), true, ok) 987 require.Equal(s.T(), requestID, casted.Request) 988 require.Equal(s.T(), node, *p2.Receiver) 989 return finalResponse, nil 990 default: 991 panic("test is totally broken") 992 } 993 } 994 995 am := NewArtifactManger() 996 am.JetCoordinator = jc 997 am.DefaultBus = mb 998 am.PulseStorage = pulseStorageMock 999 1000 // Act 1001 res, err := am.GetPendingRequest(inslogger.TestContext(s.T()), objectID) 1002 1003 // Assert 1004 require.NoError(s.T(), err) 1005 require.Equal(s.T(), parcel, res) 1006 1007 }