From 4e039bcf99003ad97082952ce82a3596bbe51661 Mon Sep 17 00:00:00 2001 From: binary_ho Date: Wed, 11 Sep 2024 22:29:38 +0900 Subject: [PATCH] Reduce CI test time by optimizing task execution (#988) Reduced CI time by optimizing task execution, including removal of unnecessary dependency step and moving complex tests. --- .github/workflows/ci.yml | 22 ++- .../server_test.go => complex/main_test.go} | 131 ++++++++---------- .../mongo_client_test.go | 4 +- test/complex/server_test.go | 105 ++++++++++++++ .../tree_concurrency_test.go | 9 +- test/integration/main_test.go | 5 + 6 files changed, 179 insertions(+), 97 deletions(-) rename test/{sharding/server_test.go => complex/main_test.go} (58%) rename test/{sharding => complex}/mongo_client_test.go (99%) create mode 100644 test/complex/server_test.go rename test/{integration => complex}/tree_concurrency_test.go (99%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 049944a6b..e438e5b88 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,7 +23,7 @@ jobs: outputs: build: ${{ steps.ci-target-check.outputs.build }} bench: ${{ steps.ci-target-check.outputs.bench }} - sharding-test: ${{ steps.ci-target-check.outputs.sharding-test }} + complex-test: ${{ steps.ci-target-check.outputs.complex-test }} steps: - name: Checkout code @@ -42,8 +42,10 @@ jobs: - 'admin/**' - 'api/converter/**' - sharding-test: + complex-test: - 'server/backend/database/**' + - 'pkg/document/**' + - 'client/**' build: name: build @@ -109,9 +111,6 @@ jobs: - name: Check out code uses: actions/checkout@v4 - - name: Get tools dependencies - run: make tools - - name: Stack run: docker compose -f build/docker/docker-compose.yml up --build -d @@ -136,12 +135,12 @@ jobs: github-token: ${{ secrets.GITHUB_TOKEN }} comment-always: true - sharding-test: - name: sharding-test + complex-test: + name: complex-test runs-on: ubuntu-latest needs: ci-target-check - if: ${{ needs.ci-target-check.outputs.sharding-test == 'true' }} + if: ${{ needs.ci-target-check.outputs.complex-test == 'true' }} steps: @@ -153,9 +152,6 @@ jobs: - name: Check out code uses: actions/checkout@v4 - - name: Get tools dependencies - run: make tools - - name: Check Docker Compose Version run: docker compose --version @@ -177,5 +173,5 @@ jobs: - name: Initialize the Mongos run: docker compose -f build/docker/sharding/docker-compose.yml exec mongos1 mongosh test /scripts/init-mongos1.js - - name: Run the tests with sharding tag - run: go test -tags sharding -race -v ./test/sharding/... + - name: Run the tests with complex tag + run: go test -tags complex -race -v ./test/complex/... diff --git a/test/sharding/server_test.go b/test/complex/main_test.go similarity index 58% rename from test/sharding/server_test.go rename to test/complex/main_test.go index cd42f0567..9ce84b62d 100644 --- a/test/sharding/server_test.go +++ b/test/complex/main_test.go @@ -1,4 +1,4 @@ -//go:build sharding +//go:build complex /* * Copyright 2023 The Yorkie Authors. All rights reserved. @@ -16,7 +16,7 @@ * limitations under the License. */ -package sharding +package complex import ( "context" @@ -27,20 +27,30 @@ import ( "testing" "connectrpc.com/connect" - + "github.com/stretchr/testify/assert" "github.com/yorkie-team/yorkie/admin" "github.com/yorkie-team/yorkie/api/yorkie/v1/v1connect" "github.com/yorkie-team/yorkie/client" + "github.com/yorkie-team/yorkie/pkg/document" "github.com/yorkie-team/yorkie/server/backend" "github.com/yorkie-team/yorkie/server/backend/database" "github.com/yorkie-team/yorkie/server/backend/database/mongo" "github.com/yorkie-team/yorkie/server/backend/housekeeping" "github.com/yorkie-team/yorkie/server/profiling/prometheus" "github.com/yorkie-team/yorkie/server/rpc" - "github.com/yorkie-team/yorkie/server/rpc/testcases" "github.com/yorkie-team/yorkie/test/helper" ) +type testResult struct { + flag bool + resultDesc string +} + +type clientAndDocPair struct { + cli *client.Client + doc *document.Document +} + var ( shardedDBNameForServer = "test-yorkie-meta-server" testRPCServer *rpc.Server @@ -132,82 +142,53 @@ func TestMain(m *testing.M) { os.Exit(code) } -func TestSDKRPCServerBackendWithShardedDB(t *testing.T) { - t.Run("activate/deactivate client test", func(t *testing.T) { - testcases.RunActivateAndDeactivateClientTest(t, testClient) - }) - - t.Run("attach/detach document test", func(t *testing.T) { - testcases.RunAttachAndDetachDocumentTest(t, testClient) - }) - - t.Run("attach/detach on removed document test", func(t *testing.T) { - testcases.RunAttachAndDetachRemovedDocumentTest(t, testClient) - }) - - t.Run("push/pull changes test", func(t *testing.T) { - testcases.RunPushPullChangeTest(t, testClient) - }) - - t.Run("push/pull on removed document test", func(t *testing.T) { - testcases.RunPushPullChangeOnRemovedDocumentTest(t, testClient) - }) +func syncClientsThenCheckEqual(t *testing.T, pairs []clientAndDocPair) bool { + assert.True(t, len(pairs) > 1) + ctx := context.Background() + // Save own changes and get previous changes. + for i, pair := range pairs { + fmt.Printf("before d%d: %s\n", i+1, pair.doc.Marshal()) + err := pair.cli.Sync(ctx) + assert.NoError(t, err) + } - t.Run("remove document test", func(t *testing.T) { - testcases.RunRemoveDocumentTest(t, testClient) - }) + // Get last client changes. + // Last client get all precede changes in above loop. + for _, pair := range pairs[:len(pairs)-1] { + err := pair.cli.Sync(ctx) + assert.NoError(t, err) + } - t.Run("remove document with invalid client state test", func(t *testing.T) { - testcases.RunRemoveDocumentWithInvalidClientStateTest(t, testClient) - }) + // Assert start. + expected := pairs[0].doc.Marshal() + fmt.Printf("after d1: %s\n", expected) + for i, pair := range pairs[1:] { + v := pair.doc.Marshal() + fmt.Printf("after d%d: %s\n", i+2, v) + if expected != v { + return false + } + } - t.Run("watch document test", func(t *testing.T) { - testcases.RunWatchDocumentTest(t, testClient) - }) + return true } -func TestAdminRPCServerBackendWithShardedDB(t *testing.T) { - t.Run("admin signup test", func(t *testing.T) { - testcases.RunAdminSignUpTest(t, testAdminClient) - }) +// activeClients creates and activates the given number of clients. +func activeClients(t *testing.T, n int) (clients []*client.Client) { + for i := 0; i < n; i++ { + c, err := client.Dial(testRPCAddr) + assert.NoError(t, err) + assert.NoError(t, c.Activate(context.Background())) - t.Run("admin login test", func(t *testing.T) { - testcases.RunAdminLoginTest(t, testAdminClient) - }) - - t.Run("admin delete account test", func(t *testing.T) { - testcases.RunAdminDeleteAccountTest(t, testAdminClient) - }) - - t.Run("admin change password test", func(t *testing.T) { - testcases.RunAdminChangePasswordTest(t, testAdminClient) - }) - - t.Run("admin create project test", func(t *testing.T) { - testcases.RunAdminCreateProjectTest(t, testAdminClient, testAdminAuthInterceptor) - }) - - t.Run("admin list projects test", func(t *testing.T) { - testcases.RunAdminListProjectsTest(t, testAdminClient, testAdminAuthInterceptor) - }) - - t.Run("admin get project test", func(t *testing.T) { - testcases.RunAdminGetProjectTest(t, testAdminClient, testAdminAuthInterceptor) - }) - - t.Run("admin update project test", func(t *testing.T) { - testcases.RunAdminUpdateProjectTest(t, testAdminClient, testAdminAuthInterceptor) - }) - - t.Run("admin list documents test", func(t *testing.T) { - testcases.RunAdminListDocumentsTest(t, testAdminClient, testAdminAuthInterceptor) - }) - - t.Run("admin get document test", func(t *testing.T) { - testcases.RunAdminGetDocumentTest(t, testClient, testAdminClient, testAdminAuthInterceptor) - }) + clients = append(clients, c) + } + return +} - t.Run("admin list changes test", func(t *testing.T) { - testcases.RunAdminListChangesTest(t, testClient, testAdminClient, testAdminAuthInterceptor) - }) +// deactivateAndCloseClients deactivates and closes the given clients. +func deactivateAndCloseClients(t *testing.T, clients []*client.Client) { + for _, c := range clients { + assert.NoError(t, c.Deactivate(context.Background())) + assert.NoError(t, c.Close()) + } } diff --git a/test/sharding/mongo_client_test.go b/test/complex/mongo_client_test.go similarity index 99% rename from test/sharding/mongo_client_test.go rename to test/complex/mongo_client_test.go index 5cb2bffe6..2fd6691fb 100644 --- a/test/sharding/mongo_client_test.go +++ b/test/complex/mongo_client_test.go @@ -1,4 +1,4 @@ -//go:build sharding +//go:build complex /* * Copyright 2023 The Yorkie Authors. All rights reserved. @@ -16,7 +16,7 @@ * limitations under the License. */ -package sharding +package complex import ( "context" diff --git a/test/complex/server_test.go b/test/complex/server_test.go new file mode 100644 index 000000000..cacc41186 --- /dev/null +++ b/test/complex/server_test.go @@ -0,0 +1,105 @@ +//go:build complex + +/* + * Copyright 2023 The Yorkie Authors. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package complex + +import ( + "testing" + + "github.com/yorkie-team/yorkie/server/rpc/testcases" +) + +func TestSDKRPCServerBackendWithShardedDB(t *testing.T) { + t.Run("activate/deactivate client test", func(t *testing.T) { + testcases.RunActivateAndDeactivateClientTest(t, testClient) + }) + + t.Run("attach/detach document test", func(t *testing.T) { + testcases.RunAttachAndDetachDocumentTest(t, testClient) + }) + + t.Run("attach/detach on removed document test", func(t *testing.T) { + testcases.RunAttachAndDetachRemovedDocumentTest(t, testClient) + }) + + t.Run("push/pull changes test", func(t *testing.T) { + testcases.RunPushPullChangeTest(t, testClient) + }) + + t.Run("push/pull on removed document test", func(t *testing.T) { + testcases.RunPushPullChangeOnRemovedDocumentTest(t, testClient) + }) + + t.Run("remove document test", func(t *testing.T) { + testcases.RunRemoveDocumentTest(t, testClient) + }) + + t.Run("remove document with invalid client state test", func(t *testing.T) { + testcases.RunRemoveDocumentWithInvalidClientStateTest(t, testClient) + }) + + t.Run("watch document test", func(t *testing.T) { + testcases.RunWatchDocumentTest(t, testClient) + }) +} + +func TestAdminRPCServerBackendWithShardedDB(t *testing.T) { + t.Run("admin signup test", func(t *testing.T) { + testcases.RunAdminSignUpTest(t, testAdminClient) + }) + + t.Run("admin login test", func(t *testing.T) { + testcases.RunAdminLoginTest(t, testAdminClient) + }) + + t.Run("admin delete account test", func(t *testing.T) { + testcases.RunAdminDeleteAccountTest(t, testAdminClient) + }) + + t.Run("admin change password test", func(t *testing.T) { + testcases.RunAdminChangePasswordTest(t, testAdminClient) + }) + + t.Run("admin create project test", func(t *testing.T) { + testcases.RunAdminCreateProjectTest(t, testAdminClient, testAdminAuthInterceptor) + }) + + t.Run("admin list projects test", func(t *testing.T) { + testcases.RunAdminListProjectsTest(t, testAdminClient, testAdminAuthInterceptor) + }) + + t.Run("admin get project test", func(t *testing.T) { + testcases.RunAdminGetProjectTest(t, testAdminClient, testAdminAuthInterceptor) + }) + + t.Run("admin update project test", func(t *testing.T) { + testcases.RunAdminUpdateProjectTest(t, testAdminClient, testAdminAuthInterceptor) + }) + + t.Run("admin list documents test", func(t *testing.T) { + testcases.RunAdminListDocumentsTest(t, testAdminClient, testAdminAuthInterceptor) + }) + + t.Run("admin get document test", func(t *testing.T) { + testcases.RunAdminGetDocumentTest(t, testClient, testAdminClient, testAdminAuthInterceptor) + }) + + t.Run("admin list changes test", func(t *testing.T) { + testcases.RunAdminListChangesTest(t, testClient, testAdminClient, testAdminAuthInterceptor) + }) +} diff --git a/test/integration/tree_concurrency_test.go b/test/complex/tree_concurrency_test.go similarity index 99% rename from test/integration/tree_concurrency_test.go rename to test/complex/tree_concurrency_test.go index b342bebcb..b7e900f5d 100644 --- a/test/integration/tree_concurrency_test.go +++ b/test/complex/tree_concurrency_test.go @@ -1,4 +1,4 @@ -//go:build integration +//go:build complex /* * Copyright 2024 The Yorkie Authors. All rights reserved. @@ -16,7 +16,7 @@ * limitations under the License. */ -package integration +package complex import ( "context" @@ -52,11 +52,6 @@ func parseSimpleXML(s string) []string { return res } -type testResult struct { - flag bool - resultDesc string -} - type rangeSelector int const ( diff --git a/test/integration/main_test.go b/test/integration/main_test.go index e63be3137..d966cf9cf 100644 --- a/test/integration/main_test.go +++ b/test/integration/main_test.go @@ -34,6 +34,11 @@ import ( "github.com/yorkie-team/yorkie/test/helper" ) +type testResult struct { + flag bool + resultDesc string +} + type clientAndDocPair struct { cli *client.Client doc *document.Document