From 4380a05bbd4260747185e2481a448e505a67de55 Mon Sep 17 00:00:00 2001 From: Travis Date: Tue, 26 Jan 2021 22:46:37 -0600 Subject: [PATCH] address some coord/node0 test issues --- api_test.go | 30 +++++++++++----------- cmd/pilosa-fsck/fsck_test.go | 3 +++ executor_test.go | 30 +++++++++++----------- http/client_test.go | 49 ++++++++++++++++++------------------ server/cluster_test.go | 24 +++++++++--------- server/server_test.go | 39 ++++++++++++++-------------- test/cluster.go | 20 +++++++++++++++ translator_test.go | 8 +++--- 8 files changed, 114 insertions(+), 89 deletions(-) diff --git a/api_test.go b/api_test.go index 6bbcdaa2c..b07e337fc 100644 --- a/api_test.go +++ b/api_test.go @@ -299,6 +299,7 @@ func TestAPI_ImportValue(t *testing.T) { ) defer c.Close() + coord := c.GetCoordinator() m0 := c.GetNode(0) m1 := c.GetNode(1) @@ -307,11 +308,11 @@ func TestAPI_ImportValue(t *testing.T) { index := "valck" field := "f" - _, err := m0.API.CreateIndex(ctx, index, pilosa.IndexOptions{Keys: true}) + _, err := coord.API.CreateIndex(ctx, index, pilosa.IndexOptions{Keys: true}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = m0.API.CreateField(ctx, index, field, pilosa.OptFieldTypeInt(math.MinInt64, math.MaxInt64)) + _, err = coord.API.CreateField(ctx, index, field, pilosa.OptFieldTypeInt(math.MinInt64, math.MaxInt64)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -334,8 +335,8 @@ func TestAPI_ImportValue(t *testing.T) { Values: values, } - qcx := m0.API.Txf().NewQcx() - if err := m0.API.ImportValue(ctx, qcx, req); err != nil { + qcx := coord.API.Txf().NewQcx() + if err := coord.API.ImportValue(ctx, qcx, req); err != nil { t.Fatal(err) } panicOn(qcx.Finish()) @@ -376,7 +377,7 @@ func TestAPI_ImportValue(t *testing.T) { t.Fatalf("creating field: %v", err) } - // Generate some keyed records. + // Generate some records. values := []float64{} colIDs := []uint64{} for i := 0; i < 10; i++ { @@ -384,8 +385,8 @@ func TestAPI_ImportValue(t *testing.T) { colIDs = append(colIDs, uint64(i)) } - // Import data with keys to the coordinator (node0) and verify that it gets - // translated and forwarded to the owner of shard 0 (node1; because of offsetModHasher) + // Import data with keys to node1 and verify that it gets translated and + // forwarded to the owner of shard 0 (node0; because of offsetModHasher) req := &pilosa.ImportValueRequest{ Index: index, Field: field, @@ -431,16 +432,16 @@ func TestAPI_ImportValue(t *testing.T) { fgnIndex := "fgnvalstr" - _, err := m0.API.CreateIndex(ctx, index, pilosa.IndexOptions{}) + _, err := coord.API.CreateIndex(ctx, index, pilosa.IndexOptions{}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = m0.API.CreateIndex(ctx, fgnIndex, pilosa.IndexOptions{Keys: true}) + _, err = coord.API.CreateIndex(ctx, fgnIndex, pilosa.IndexOptions{Keys: true}) if err != nil { t.Fatalf("creating foreign index: %v", err) } - _, err = m0.API.CreateField(ctx, index, field, + _, err = coord.API.CreateField(ctx, index, field, pilosa.OptFieldTypeInt(0, math.MaxInt64), pilosa.OptFieldForeignIndex(fgnIndex), ) @@ -457,8 +458,9 @@ func TestAPI_ImportValue(t *testing.T) { colIDs = append(colIDs, uint64(i)) } - // Import data with keys to the coordinator (node0) and verify that it gets - // translated and forwarded to the owner of shard 0 (node1; because of offsetModHasher) + // Import data with keys to the node0 and verify that it gets translated + // and forwarded to the owner of shard 0 (node1; because of + // offsetModHasher) req := &pilosa.ImportValueRequest{ Index: index, Field: field, @@ -473,8 +475,8 @@ func TestAPI_ImportValue(t *testing.T) { pql := fmt.Sprintf(`Row(%s=="strval-110")`, field) - // Query node0. - if res, err := m0.API.Query(ctx, &pilosa.QueryRequest{Index: index, Query: pql}); err != nil { + // Query node1. + if res, err := m1.API.Query(ctx, &pilosa.QueryRequest{Index: index, Query: pql}); err != nil { t.Fatal(err) } else if ids := res.Results[0].(*pilosa.Row).Columns(); !reflect.DeepEqual(ids, []uint64{1}) { t.Fatalf("unexpected columns: observerd %+v; expected '%+v'", ids, []uint64{1}) diff --git a/cmd/pilosa-fsck/fsck_test.go b/cmd/pilosa-fsck/fsck_test.go index ab544e06f..2555215cc 100644 --- a/cmd/pilosa-fsck/fsck_test.go +++ b/cmd/pilosa-fsck/fsck_test.go @@ -402,6 +402,9 @@ func check(dirs []string, cfg *FsckConfig, targetIndex string, targetPartition i return firstChecksum, nil } +// These are here to satisfy the linter in CI while the test is being skipped. +var _ = getFwdRev +var _ = check var _ = getChecksums func getChecksums(dirs []string, cfg *FsckConfig, targetPartition int) (chksum []string) { diff --git a/executor_test.go b/executor_test.go index 497100645..447b1aea0 100644 --- a/executor_test.go +++ b/executor_test.go @@ -2957,11 +2957,11 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { hldr0 := c.GetHolder(0) hldr1 := c.GetHolder(1) - _, err := c.GetNode(0).API.CreateIndex(context.Background(), "i", pilosa.IndexOptions{}) + _, err := c.GetCoordinator().API.CreateIndex(context.Background(), "i", pilosa.IndexOptions{}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = c.GetNode(0).API.CreateField(context.Background(), "i", "f", pilosa.OptFieldTypeSet(pilosa.DefaultCacheType, pilosa.DefaultCacheSize)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "i", "f", pilosa.OptFieldTypeSet(pilosa.DefaultCacheType, pilosa.DefaultCacheSize)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -2994,7 +2994,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("remote with timestamp", func(t *testing.T) { - _, err = c.GetNode(0).API.CreateField(context.Background(), "i", "z", pilosa.OptFieldTypeTime("Y")) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "i", "z", pilosa.OptFieldTypeTime("Y")) if err != nil { t.Fatalf("creating field: %v", err) } @@ -3009,7 +3009,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("remote topn", func(t *testing.T) { - _, err = c.GetNode(0).API.CreateField(context.Background(), "i", "fn", pilosa.OptFieldTypeSet(pilosa.CacheTypeRanked, 100)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "i", "fn", pilosa.OptFieldTypeSet(pilosa.CacheTypeRanked, 100)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -3056,7 +3056,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("remote groupBy", func(t *testing.T) { - if res, err := c.GetNode(1).API.Query(context.Background(), &pilosa.QueryRequest{ + if res, err := c.GetNode(0).API.Query(context.Background(), &pilosa.QueryRequest{ Index: "i", Query: `GroupBy(Rows(f))`, }); err != nil { @@ -3072,7 +3072,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("remote groupBy on ints", func(t *testing.T) { - _, err = c.GetNode(0).API.CreateField(context.Background(), "i", "fint", pilosa.OptFieldTypeInt(-1000, 1000)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "i", "fint", pilosa.OptFieldTypeInt(-1000, 1000)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -3114,7 +3114,7 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("groupBy on ints with offset regression", func(t *testing.T) { - _, err = c.GetNode(0).API.CreateField(context.Background(), "i", "hint", pilosa.OptFieldTypeInt(1, 1000)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "i", "hint", pilosa.OptFieldTypeInt(1, 1000)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -3145,12 +3145,12 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("Row on ints with ASSIGN condition", func(t *testing.T) { - _, err := c.GetNode(0).API.CreateIndex(context.Background(), "intidx", pilosa.IndexOptions{}) + _, err := c.GetCoordinator().API.CreateIndex(context.Background(), "intidx", pilosa.IndexOptions{}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = c.GetNode(0).API.CreateField(context.Background(), "intidx", "gint", pilosa.OptFieldTypeInt(-1000, 1000)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "intidx", "gint", pilosa.OptFieldTypeInt(-1000, 1000)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -3180,12 +3180,12 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("Row on decimals with ASSIGN condition", func(t *testing.T) { - _, err := c.GetNode(0).API.CreateIndex(context.Background(), "decidx", pilosa.IndexOptions{}) + _, err := c.GetCoordinator().API.CreateIndex(context.Background(), "decidx", pilosa.IndexOptions{}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = c.GetNode(0).API.CreateField(context.Background(), "decidx", "fdec", pilosa.OptFieldTypeDecimal(0)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "decidx", "fdec", pilosa.OptFieldTypeDecimal(0)) if err != nil { t.Fatalf("creating field: %v", err) } @@ -3214,19 +3214,19 @@ func TestExecutor_Execute_Remote_Row(t *testing.T) { }) t.Run("Row on foreign key with ASSIGN condition", func(t *testing.T) { - _, err := c.GetNode(0).API.CreateIndex(context.Background(), "parent", pilosa.IndexOptions{Keys: true}) + _, err := c.GetCoordinator().API.CreateIndex(context.Background(), "parent", pilosa.IndexOptions{Keys: true}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = c.GetNode(0).API.CreateField(context.Background(), "parent", "general", pilosa.OptFieldTypeSet(pilosa.DefaultCacheType, pilosa.DefaultCacheSize)) + _, err = c.GetCoordinator().API.CreateField(context.Background(), "parent", "general", pilosa.OptFieldTypeSet(pilosa.DefaultCacheType, pilosa.DefaultCacheSize)) if err != nil { t.Fatalf("creating field: %v", err) } - _, err = c.GetNode(0).API.CreateIndex(context.Background(), "child", pilosa.IndexOptions{Keys: false}) + _, err = c.GetCoordinator().API.CreateIndex(context.Background(), "child", pilosa.IndexOptions{Keys: false}) if err != nil { t.Fatalf("creating index: %v", err) } - _, err = c.GetNode(0).API.CreateField(context.Background(), "child", "parentid", + _, err = c.GetCoordinator().API.CreateField(context.Background(), "child", "parentid", pilosa.OptFieldForeignIndex("parent"), pilosa.OptFieldTypeInt(-9223372036854775808, 9223372036854775807), ) diff --git a/http/client_test.go b/http/client_test.go index c89ee7dd4..0077ae555 100644 --- a/http/client_test.go +++ b/http/client_test.go @@ -49,15 +49,16 @@ func TestClient_MultiNode(t *testing.T) { ) defer c.Close() - hldr := []test.Holder{} - for _, command := range c.Nodes { - hldr = append(hldr, test.Holder{Holder: command.Server.Holder()}) - } + hldr0 := c.GetHolder(0) + hldr1 := c.GetHolder(1) + hldr2 := c.GetHolder(2) - // Create a dispersed set of bitmaps across 3 nodes such that each individual node and shard width increment would reveal a different TopN. + // Create a dispersed set of bitmaps across 3 nodes such that each + // individual node and shard width increment would reveal a different TopN. shardNums := []uint64{1, 2, 6} - // This was generated with: `owns := s[i].Handler.Handler.API.Cluster.OwnsShards("i", 20, s[i].HostURI())` + // This was generated with: + // `owns := s[i].Handler.Handler.API.Cluster.OwnsShards("i", 20, s[i].HostURI())` owns := [][]uint64{ {1, 3, 4, 8, 10, 13, 17, 19}, {2, 5, 7, 11, 12, 14, 18}, @@ -96,26 +97,26 @@ func TestClient_MultiNode(t *testing.T) { t.Fatalf("creating field: %v", err) } - hldr[0].MustSetBits("i", "f", 100, baseBit0+10) - hldr[0].MustSetBits("i", "f", 4, baseBit0+10, baseBit0+11, baseBit0+12) - hldr[0].MustSetBits("i", "f", 4, baseBit0+10, baseBit0+11, baseBit0+12, baseBit0+13, baseBit0+14, baseBit0+15) - hldr[0].MustSetBits("i", "f", 2, baseBit0+1, baseBit0+2, baseBit0+3, baseBit0+4) - hldr[0].MustSetBits("i", "f", 3, baseBit0+1, baseBit0+2, baseBit0+3, baseBit0+4, baseBit0+5) - hldr[0].MustSetBits("i", "f", 22, baseBit0+1, baseBit0+2) + hldr0.MustSetBits("i", "f", 100, baseBit0+10) + hldr0.MustSetBits("i", "f", 4, baseBit0+10, baseBit0+11, baseBit0+12) + hldr0.MustSetBits("i", "f", 4, baseBit0+10, baseBit0+11, baseBit0+12, baseBit0+13, baseBit0+14, baseBit0+15) + hldr0.MustSetBits("i", "f", 2, baseBit0+1, baseBit0+2, baseBit0+3, baseBit0+4) + hldr0.MustSetBits("i", "f", 3, baseBit0+1, baseBit0+2, baseBit0+3, baseBit0+4, baseBit0+5) + hldr0.MustSetBits("i", "f", 22, baseBit0+1, baseBit0+2) - hldr[1].MustSetBits("i", "f", 99, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4) - hldr[1].MustSetBits("i", "f", 100, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4, baseBit1+5, baseBit1+6, baseBit1+7, baseBit1+8, baseBit1+9, baseBit1+10) - hldr[1].MustSetBits("i", "f", 98, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4, baseBit1+5, baseBit1+6) - hldr[1].MustSetBits("i", "f", 1, baseBit1+4) - hldr[1].MustSetBits("i", "f", 22, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4, baseBit1+5) + hldr1.MustSetBits("i", "f", 99, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4) + hldr1.MustSetBits("i", "f", 100, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4, baseBit1+5, baseBit1+6, baseBit1+7, baseBit1+8, baseBit1+9, baseBit1+10) + hldr1.MustSetBits("i", "f", 98, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4, baseBit1+5, baseBit1+6) + hldr1.MustSetBits("i", "f", 1, baseBit1+4) + hldr1.MustSetBits("i", "f", 22, baseBit1+1, baseBit1+2, baseBit1+3, baseBit1+4, baseBit1+5) - hldr[2].MustSetBits("i", "f", 24, baseBit2+10, baseBit2+11, baseBit2+12, baseBit2+13, baseBit2+14) - hldr[2].MustSetBits("i", "f", 20, baseBit2+10, baseBit2+11, baseBit2+12, baseBit2+13) - hldr[2].MustSetBits("i", "f", 21, baseBit2+10) - hldr[2].MustSetBits("i", "f", 100, baseBit2+10) - hldr[2].MustSetBits("i", "f", 99, baseBit2+10, baseBit2+11, baseBit2+12) - hldr[2].MustSetBits("i", "f", 98, baseBit2+10, baseBit2+11) - hldr[2].MustSetBits("i", "f", 22, baseBit2+10, baseBit2+11, baseBit2+12) + hldr2.MustSetBits("i", "f", 24, baseBit2+10, baseBit2+11, baseBit2+12, baseBit2+13, baseBit2+14) + hldr2.MustSetBits("i", "f", 20, baseBit2+10, baseBit2+11, baseBit2+12, baseBit2+13) + hldr2.MustSetBits("i", "f", 21, baseBit2+10) + hldr2.MustSetBits("i", "f", 100, baseBit2+10) + hldr2.MustSetBits("i", "f", 99, baseBit2+10, baseBit2+11, baseBit2+12) + hldr2.MustSetBits("i", "f", 98, baseBit2+10, baseBit2+11) + hldr2.MustSetBits("i", "f", 22, baseBit2+10, baseBit2+11, baseBit2+12) // Rebuild the RankCache. // We have to do this to avoid the 10-second cache invalidation delay diff --git a/server/cluster_test.go b/server/cluster_test.go index 9108771ac..973c59960 100644 --- a/server/cluster_test.go +++ b/server/cluster_test.go @@ -695,8 +695,8 @@ func TestCluster_GossipMembership(t *testing.T) { func TestClusterResize_RemoveNode(t *testing.T) { cluster := test.MustRunCluster(t, 3) defer cluster.Close() - m0 := cluster.GetNode(0) - m1 := cluster.GetNode(1) + coord := cluster.GetCoordinator() + other := cluster.GetNonCoordinator() mustNodeID := func(baseURL string) string { body := test.Do(t, "GET", fmt.Sprintf("%s/status", baseURL), "").Body @@ -712,7 +712,7 @@ func TestClusterResize_RemoveNode(t *testing.T) { } t.Run("ErrorRemoveInvalidNode", func(t *testing.T) { - resp := test.Do(t, "POST", m0.URL()+"/cluster/resize/remove-node", `{"id": "invalid-node-id"}`) + resp := test.Do(t, "POST", coord.URL()+"/cluster/resize/remove-node", `{"id": "invalid-node-id"}`) expBody := "removing node: finding node to remove: node with provided ID does not exist" if resp.StatusCode != http.StatusNotFound { t.Fatalf("expected StatusCode %d but got %d", http.StatusNotFound, resp.StatusCode) @@ -722,8 +722,8 @@ func TestClusterResize_RemoveNode(t *testing.T) { }) t.Run("ErrorRemoveCoordinator", func(t *testing.T) { - nodeID := mustNodeID(m0.URL()) - resp := test.Do(t, "POST", m0.URL()+"/cluster/resize/remove-node", fmt.Sprintf(`{"id": "%s"}`, nodeID)) + nodeID := mustNodeID(coord.URL()) + resp := test.Do(t, "POST", coord.URL()+"/cluster/resize/remove-node", fmt.Sprintf(`{"id": "%s"}`, nodeID)) expBody := "removing node: calling node leave: coordinator cannot be removed; first, make a different node the new coordinator" if resp.StatusCode != http.StatusInternalServerError { @@ -734,9 +734,9 @@ func TestClusterResize_RemoveNode(t *testing.T) { }) t.Run("ErrorRemoveOnNonCoordinator", func(t *testing.T) { - coordinatorNodeID := mustNodeID(m0.URL()) - nodeID := mustNodeID(m1.URL()) - resp := test.Do(t, "POST", m1.URL()+"/cluster/resize/remove-node", fmt.Sprintf(`{"id": "%s"}`, nodeID)) + coordinatorNodeID := mustNodeID(coord.URL()) + nodeID := mustNodeID(other.URL()) + resp := test.Do(t, "POST", other.URL()+"/cluster/resize/remove-node", fmt.Sprintf(`{"id": "%s"}`, nodeID)) expBody := fmt.Sprintf("removing node: calling node leave: node removal requests are only valid on the coordinator node: %s", coordinatorNodeID) if resp.StatusCode != http.StatusInternalServerError { @@ -747,7 +747,7 @@ func TestClusterResize_RemoveNode(t *testing.T) { }) t.Run("ErrorRemoveWithoutReplicas", func(t *testing.T) { - client0 := m0.Client() + client0 := coord.Client() // Create indexes and fields on one node. if err := client0.CreateIndex(context.Background(), "i", pilosa.IndexOptions{}); err != nil && err != pilosa.ErrIndexExists { @@ -763,12 +763,12 @@ func TestClusterResize_RemoveNode(t *testing.T) { setColumns += fmt.Sprintf("Set(%d, f=1) ", i*pilosa.ShardWidth) } - if _, err := m0.Query(t, "i", "", setColumns); err != nil { + if _, err := coord.Query(t, "i", "", setColumns); err != nil { t.Fatal(err) } - nodeID := mustNodeID(m1.URL()) - resp := test.Do(t, "POST", m0.URL()+"/cluster/resize/remove-node", fmt.Sprintf(`{"id": "%s"}`, nodeID)) + nodeID := mustNodeID(other.URL()) + resp := test.Do(t, "POST", coord.URL()+"/cluster/resize/remove-node", fmt.Sprintf(`{"id": "%s"}`, nodeID)) expBody := "not enough data to perform resize" if resp.StatusCode != http.StatusInternalServerError { t.Fatalf("expected StatusCode %d but got %d", http.StatusInternalServerError, resp.StatusCode) diff --git a/server/server_test.go b/server/server_test.go index c19a49428..f1926729c 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -387,32 +387,31 @@ func TestTransactionsAPI(t *testing.T) { cluster := test.MustRunCluster(t, 3) defer cluster.Close() - api0 := cluster.GetNode(0).API - api1 := cluster.GetNode(1).API + coord := cluster.GetCoordinator().API + other := cluster.GetNonCoordinator().API ctx := context.Background() - //api2 := cluster.GetNode(2).API // can fetch empty transactions - if trnsMap, err := api0.Transactions(ctx); err != nil { + if trnsMap, err := coord.Transactions(ctx); err != nil { t.Fatalf("getting transactions: %v", err) } else if len(trnsMap) != 0 { t.Fatalf("unexpectedly has transactions: %v", trnsMap) } // can't fetch transactions from non-coordinator - if _, err := api1.Transactions(ctx); err != pilosa.ErrNodeNotCoordinator { + if _, err := other.Transactions(ctx); err != pilosa.ErrNodeNotCoordinator { t.Errorf("api1 should return ErrNodeNotCoordinator when asked for transactions but got: %v", err) } // can start transaction - if trns, err := api0.StartTransaction(ctx, "a", time.Minute, false, false); err != nil { + if trns, err := coord.StartTransaction(ctx, "a", time.Minute, false, false); err != nil { t.Errorf("couldn't start transaction: %v", err) } else { test.CompareTransactions(t, &pilosa.Transaction{ID: "a", Active: true, Timeout: time.Minute, Deadline: time.Now().Add(time.Minute)}, trns) } // can retrieve transaction from other nodes with remote=true - if trns, err := api1.GetTransaction(ctx, "a", true); err != nil { + if trns, err := other.GetTransaction(ctx, "a", true); err != nil { t.Errorf("couldn't fetch transaction from other node with remote=true: %v", err) } else { test.CompareTransactions(t, &pilosa.Transaction{ID: "a", Active: true, Timeout: time.Minute, Deadline: time.Now().Add(time.Minute)}, trns) @@ -420,7 +419,7 @@ func TestTransactionsAPI(t *testing.T) { // can start transaction with blank id and get uuid back id := "" - if trns, err := api0.StartTransaction(ctx, id, time.Minute, false, false); err != nil { + if trns, err := coord.StartTransaction(ctx, id, time.Minute, false, false); err != nil { t.Errorf("couldn't start transaction: %v", err) } else { id = trns.ID @@ -431,54 +430,54 @@ func TestTransactionsAPI(t *testing.T) { } // can't finish transaction on non-coordinator - if _, err := api1.FinishTransaction(ctx, id, false); err != pilosa.ErrNodeNotCoordinator { + if _, err := other.FinishTransaction(ctx, id, false); err != pilosa.ErrNodeNotCoordinator { t.Errorf("unexpected error is not ErrNodeNotCoordinator: %v", err) } // can finish transaction - if _, err := api0.FinishTransaction(ctx, id, false); err != nil { + if _, err := coord.FinishTransaction(ctx, id, false); err != nil { t.Errorf("couldn't finish transaction: %v", err) } // can finish previous transaction - if _, err := api0.FinishTransaction(ctx, "a", false); err != nil { + if _, err := coord.FinishTransaction(ctx, "a", false); err != nil { t.Errorf("couldn't finish transaction a: %v", err) } // can start exclusive transaction - if te, err := api0.StartTransaction(ctx, "exc", time.Minute, true, false); err != nil { + if te, err := coord.StartTransaction(ctx, "exc", time.Minute, true, false); err != nil { t.Errorf("couldn't start exclusive transaction: %v", err) } else if !te.Active { t.Errorf("expected exclusive transaction to be active: %+v", te) } // can finish exclusive transaction - if _, err := api0.FinishTransaction(ctx, "exc", false); err != nil { + if _, err := coord.FinishTransaction(ctx, "exc", false); err != nil { t.Errorf("couldn't finish exclusive transaction: %v", err) } // can start transaction (with same name as previous finished transaction) - if trns, err := api0.StartTransaction(ctx, "a", time.Minute, false, false); err != nil { + if trns, err := coord.StartTransaction(ctx, "a", time.Minute, false, false); err != nil { t.Errorf("couldn't start transaction: %v", err) } else { test.CompareTransactions(t, &pilosa.Transaction{ID: "a", Active: true, Timeout: time.Minute, Deadline: time.Now().Add(time.Minute)}, trns) } // can start exclusive transaction and is not immediately active - if te, err := api0.StartTransaction(ctx, "exc", time.Minute, true, false); err != nil { + if te, err := coord.StartTransaction(ctx, "exc", time.Minute, true, false); err != nil { t.Errorf("couldn't start exclusive transaction: %v", err) } else if te.Active { t.Errorf("expected exclusive transaction to be inactive: %+v", te) } // can finish non-exclusive transaction - if _, err := api0.FinishTransaction(ctx, "a", false); err != nil { + if _, err := coord.FinishTransaction(ctx, "a", false); err != nil { t.Errorf("couldn't finish transaction a: %v", err) } // can poll exclusive transaction and is active var excTrns *pilosa.Transaction - if trns, err := api0.GetTransaction(ctx, "exc", false); err != nil { + if trns, err := coord.GetTransaction(ctx, "exc", false); err != nil { t.Errorf("couldn't poll exclusive transaction: %v", err) } else { excTrns = &pilosa.Transaction{ID: "exc", Active: true, Exclusive: true, Timeout: time.Minute, Deadline: time.Now().Add(time.Minute)} @@ -486,7 +485,7 @@ func TestTransactionsAPI(t *testing.T) { } // can't start another exclusive transaction - if trns, err := api0.StartTransaction(ctx, "exc2", time.Minute, true, false); errors.Cause(err) != pilosa.ErrTransactionExclusive { + if trns, err := coord.StartTransaction(ctx, "exc2", time.Minute, true, false); errors.Cause(err) != pilosa.ErrTransactionExclusive { t.Errorf("unexpected error: %v", err) } else { // returned transaction should be the exclusive one which is blocking this one @@ -494,14 +493,14 @@ func TestTransactionsAPI(t *testing.T) { } // can't keep the second exclusive name but make it nonexclusive and start a transaction - if trns, err := api0.StartTransaction(ctx, "exc2", time.Minute, false, false); errors.Cause(err) != pilosa.ErrTransactionExclusive { + if trns, err := coord.StartTransaction(ctx, "exc2", time.Minute, false, false); errors.Cause(err) != pilosa.ErrTransactionExclusive { t.Errorf("unexpected error: %v", err) } else { test.CompareTransactions(t, excTrns, trns) } // transaction is active on other nodes with remote=true - if trns, err := api1.GetTransaction(ctx, "exc", true); err != nil { + if trns, err := other.GetTransaction(ctx, "exc", true); err != nil { t.Errorf("couldn't poll exclusive transaction: %v", err) } else { test.CompareTransactions(t, &pilosa.Transaction{ID: "exc", Active: true, Exclusive: true, Timeout: time.Minute, Deadline: time.Now().Add(time.Minute)}, trns) diff --git a/test/cluster.go b/test/cluster.go index d7dd224c2..cd22bfff7 100644 --- a/test/cluster.go +++ b/test/cluster.go @@ -178,6 +178,17 @@ func (c *Cluster) GetHolder(n int) *Holder { return &Holder{Holder: c.GetNode(n).Server.Holder()} } +// GetCoordinatorHolder returns the Holder for the coordinator node. +func (c *Cluster) GetCoordinatorHolder() *Holder { + return &Holder{Holder: c.GetCoordinator().Server.Holder()} +} + +// GetNonCoordinatorHolder returns the Holder for the the first non-coordinator +// node in the list of nodes. +func (c *Cluster) GetNonCoordinatorHolder() *Holder { + return &Holder{Holder: c.GetNonCoordinator().Server.Holder()} +} + func (c *Cluster) Len() int { return len(c.Nodes) } @@ -442,6 +453,15 @@ func (c *Cluster) Close() error { return nil } +func (c *Cluster) CloseAndRemoveNonCoordinator() error { + for i, n := range c.Nodes { + if !n.IsCoordinator() { + return c.CloseAndRemove(i) + } + } + return errors.New("could not find non-coordinator node") +} + func (c *Cluster) CloseAndRemove(n int) error { if n < 0 || n >= len(c.Nodes) { return fmt.Errorf("close/remove from cluster: index %d out of range (len %d)", n, len(c.Nodes)) diff --git a/translator_test.go b/translator_test.go index b57b3e397..39a444bc7 100644 --- a/translator_test.go +++ b/translator_test.go @@ -514,16 +514,16 @@ func TestTranslation_Replication(t *testing.T) { exp := `{"results":[{"attrs":{},"columns":[],"keys":["x1","x2"]}]}` if !test.CheckClusterState(coord, pilosa.ClusterStateNormal, 1000) { - t.Fatalf("unexpected node0 cluster state: %s", coord.API.State()) + t.Fatalf("unexpected coord cluster state: %s", coord.API.State()) } else if !test.CheckClusterState(other, pilosa.ClusterStateNormal, 1000) { - t.Fatalf("unexpected node1 cluster state: %s", other.API.State()) + t.Fatalf("unexpected other cluster state: %s", other.API.State()) } // Verify the data exists coord.QueryExpect(t, idx, "", `Row(f=1)`, exp) - // Kill one node. - if err := c.CloseAndRemove(1); err != nil { + // Kill a non-coordinator node. + if err := c.CloseAndRemoveNonCoordinator(); err != nil { t.Fatal(err) }