(t *testing.T)
| 604 | } |
| 605 | |
| 606 | func TestReplicatorPutObjects(t *testing.T) { |
| 607 | var ( |
| 608 | cls = "C1" |
| 609 | shard = "SH1" |
| 610 | nodes = []string{"A", "B"} |
| 611 | ctx = context.Background() |
| 612 | objs = []*storobj.Object{{}, {}, {}} |
| 613 | resp1 = replica.SimpleResponse{[]replicaerrors.Error{{}}} |
| 614 | ) |
| 615 | |
| 616 | testCases := []struct { |
| 617 | variant string |
| 618 | isMultiTenant bool |
| 619 | }{ |
| 620 | {"MultiTenant", true}, |
| 621 | {"SingleTenant", false}, |
| 622 | } |
| 623 | |
| 624 | for _, tc := range testCases { |
| 625 | t.Run(fmt.Sprintf("SuccessWithConsistencyLevelAll_%v", tc.variant), func(t *testing.T) { |
| 626 | f := newFakeFactory(t, "C1", shard, nodes, tc.isMultiTenant) |
| 627 | rep := f.newReplicator() |
| 628 | resp := replica.SimpleResponse{Errors: make([]replicaerrors.Error, 3)} |
| 629 | for _, n := range nodes { |
| 630 | f.WClient.On("PutObjects", mock.Anything, n, cls, shard, anyVal, objs, uint64(123)).Return(resp, nil) |
| 631 | f.WClient.On("Commit", ctx, n, cls, shard, anyVal, anyVal).Return(nil) |
| 632 | } |
| 633 | errs := rep.PutObjects(ctx, shard, objs, types.ConsistencyLevelAll, 123) |
| 634 | assert.Equal(t, []error{nil, nil, nil}, errs) |
| 635 | }) |
| 636 | |
| 637 | t.Run(fmt.Sprintf("SuccessWithConsistencyLevelOne_%v", tc.variant), func(t *testing.T) { |
| 638 | nodes := []string{"A", "B", "C"} |
| 639 | f := newFakeFactory(t, "C1", shard, nodes, tc.isMultiTenant) |
| 640 | rep := f.newReplicator() |
| 641 | |
| 642 | // Phase one: branch on host(make it deterministic). Only "A" can succeed; all other hosts |
| 643 | // return a phase-one error. This guarantees: |
| 644 | // - multiple replicas are contacted |
| 645 | // - only "A" is eligible for commit. |
| 646 | f.WClient.EXPECT(). |
| 647 | PutObjects(mock.Anything, mock.Anything, cls, shard, anyVal, objs, uint64(0)). |
| 648 | RunAndReturn(func(ctx context.Context, host, index, shard, reqID string, os []*storobj.Object, sv uint64) (replica.SimpleResponse, error) { |
| 649 | if host == "A" { |
| 650 | return resp1, nil |
| 651 | } |
| 652 | return replica.SimpleResponse{}, errAny |
| 653 | }) |
| 654 | |
| 655 | // Commit only on the successful node. |
| 656 | var wg sync.WaitGroup |
| 657 | wg.Add(1) |
| 658 | f.WClient.On("Commit", ctx, "A", cls, shard, anyVal, anyVal).Return(nil).RunFn = func(a mock.Arguments) { |
| 659 | defer wg.Done() |
| 660 | resp := a[5].(*replica.SimpleResponse) |
| 661 | *resp = replica.SimpleResponse{Errors: make([]replicaerrors.Error, 3)} |
| 662 | } |
| 663 |
nothing calls this directly
no test coverage detected
searching dependent graphs…