You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kvrocks.apache.org by ti...@apache.org on 2022/09/03 17:29:07 UTC

[incubator-kvrocks] branch unstable updated: refactor: write integration tests in Golang (#806)

This is an automated email from the ASF dual-hosted git repository.

tison pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/incubator-kvrocks.git


The following commit(s) were added to refs/heads/unstable by this push:
     new c9d175a  refactor: write integration tests in Golang (#806)
c9d175a is described below

commit c9d175aee1b2f52c1ba281d85dc5d9524b519b9a
Author: tison <wa...@gmail.com>
AuthorDate: Sun Sep 4 01:29:00 2022 +0800

    refactor: write integration tests in Golang (#806)
    
    Signed-off-by: tison <wa...@gmail.com>
---
 .github/workflows/kvrocks.yaml            |  21 +++++
 tests/gocase/go.mod                       |  16 ++++
 tests/gocase/go.sum                       |  30 ++++++++
 tests/gocase/unit/command/command_test.go |  77 +++++++++++++++++++
 tests/gocase/unit/info/info_test.go       | 103 +++++++++++++++++++++++++
 tests/gocase/util/server.go               | 122 ++++++++++++++++++++++++++++++
 tests/gocase/workspace/.gitignore         |   1 +
 tests/tcl/tests/test_helper.tcl           |   1 -
 tests/tcl/tests/unit/command.tcl          |  85 ---------------------
 tools/ci/licenserc.yml                    |   3 +-
 10 files changed, 371 insertions(+), 88 deletions(-)

diff --git a/.github/workflows/kvrocks.yaml b/.github/workflows/kvrocks.yaml
index a6106ff..71aa3be 100644
--- a/.github/workflows/kvrocks.yaml
+++ b/.github/workflows/kvrocks.yaml
@@ -160,6 +160,27 @@ jobs:
           export ${{ matrix.runtime_env_vars }}
           ./build/unittest
 
+      - name: Setup Go
+        uses: actions/setup-go@v3
+        with:
+          go-version: 1.19.x
+
+      - name: Run Go Integration Cases
+        working-directory: tests/gocase
+        run: |
+          export ${{ matrix.runtime_env_vars }}
+          export KVROCKS_BIN_PATH="$GITHUB_WORKSPACE/build/kvrocks"
+          export GO_CASE_WORKSPACE="$GITHUB_WORKSPACE/tests/gocase/workspace"
+          go test -v ./...
+          SANITIZER_OUTPUT=$(grep "Sanitizer:" workspace -r || true)
+          if [[ $SANITIZER_OUTPUT ]]; then
+            echo "$SANITIZER_OUTPUT"
+            echo "\ndetail reports:\n"
+            cat $(find workspace -iname stderr)
+            echo "sanitizer error was reported, exiting..."
+            exit 1
+          fi
+
       - name: Run Redis Tcl Test
         run: |
           export ${{ matrix.runtime_env_vars }}
diff --git a/tests/gocase/go.mod b/tests/gocase/go.mod
new file mode 100644
index 0000000..cb7138c
--- /dev/null
+++ b/tests/gocase/go.mod
@@ -0,0 +1,16 @@
+module github.com/apache/incubator-kvrocks/tests/gocase
+
+go 1.19
+
+require (
+	github.com/go-redis/redis/v9 v9.0.0-beta.2
+	github.com/stretchr/testify v1.8.0
+)
+
+require (
+	github.com/cespare/xxhash/v2 v2.1.2 // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/tests/gocase/go.sum b/tests/gocase/go.sum
new file mode 100644
index 0000000..8a6efea
--- /dev/null
+++ b/tests/gocase/go.sum
@@ -0,0 +1,30 @@
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
+github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/go-redis/redis/v9 v9.0.0-beta.2 h1:ZSr84TsnQyKMAg8gnV+oawuQezeJR11/09THcWCQzr4=
+github.com/go-redis/redis/v9 v9.0.0-beta.2/go.mod h1:Bldcd/M/bm9HbnNPi/LUtYBSD8ttcZYBMupwMXhdU0o=
+github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
+github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
+golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/tests/gocase/unit/command/command_test.go b/tests/gocase/unit/command/command_test.go
new file mode 100644
index 0000000..b576c05
--- /dev/null
+++ b/tests/gocase/unit/command/command_test.go
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 command
+
+import (
+	"context"
+	"testing"
+
+	"github.com/apache/incubator-kvrocks/tests/gocase/util"
+	"github.com/stretchr/testify/require"
+)
+
+func TestCommand(t *testing.T) {
+	srv, err := util.StartServer(t, map[string]string{})
+	require.NoError(t, err)
+	defer srv.Close()
+
+	ctx := context.Background()
+	rdb := srv.NewClient()
+	defer func() { require.NoError(t, rdb.Close()) }()
+
+	t.Run("Kvrocks supports 180 commands currently", func(t *testing.T) {
+		r := rdb.Do(ctx, "COMMAND", "COUNT")
+		v, err := r.Int()
+		require.NoError(t, err)
+		require.Equal(t, 180, v)
+	})
+
+	t.Run("acquire GET command info by COMMAND INFO", func(t *testing.T) {
+		r := rdb.Do(ctx, "COMMAND", "INFO", "GET")
+		vs, err := r.Slice()
+		require.NoError(t, err)
+		require.Len(t, vs, 1)
+		v := vs[0].([]interface{})
+		require.Len(t, v, 6)
+		require.Equal(t, "get", v[0])
+		require.EqualValues(t, 2, v[1])
+		require.Equal(t, []interface{}{"readonly"}, v[2])
+		require.EqualValues(t, 1, v[3])
+		require.EqualValues(t, 1, v[4])
+		require.EqualValues(t, 1, v[5])
+	})
+
+	t.Run("command entry length check", func(t *testing.T) {
+		r := rdb.Do(ctx, "COMMAND")
+		vs, err := r.Slice()
+		require.NoError(t, err)
+		v := vs[0].([]interface{})
+		require.Len(t, v, 6)
+	})
+
+	t.Run("get keys of commands by COMMAND GETKEYS", func(t *testing.T) {
+		r := rdb.Do(ctx, "COMMAND", "GETKEYS", "GET", "test")
+		vs, err := r.Slice()
+		require.NoError(t, err)
+		require.Len(t, vs, 1)
+		require.Equal(t, "test", vs[0])
+	})
+}
diff --git a/tests/gocase/unit/info/info_test.go b/tests/gocase/unit/info/info_test.go
new file mode 100644
index 0000000..54acac0
--- /dev/null
+++ b/tests/gocase/unit/info/info_test.go
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 command
+
+import (
+	"context"
+	"fmt"
+	"regexp"
+	"strconv"
+	"strings"
+	"testing"
+	"time"
+
+	"github.com/apache/incubator-kvrocks/tests/gocase/util"
+	"github.com/stretchr/testify/require"
+)
+
+func TestInfo(t *testing.T) {
+	srv, err := util.StartServer(t, map[string]string{})
+	require.NoError(t, err)
+	defer srv.Close()
+
+	ctx := context.Background()
+	rdb := srv.NewClient()
+	defer func() { require.NoError(t, rdb.Close()) }()
+
+	FindInfoEntry := func(t *testing.T, section string, key string) string {
+		r := rdb.Info(ctx, section)
+		p := regexp.MustCompile(fmt.Sprintf("%s:(.+)", key))
+		ms := p.FindStringSubmatch(r.Val())
+		require.Len(t, ms, 2)
+		return strings.TrimSpace(ms[1])
+	}
+
+	MustAtoi := func(t *testing.T, s string) int {
+		i, err := strconv.Atoi(s)
+		require.NoError(t, err)
+		return i
+	}
+
+	t.Run("get rocksdb ops by INFO", func(t *testing.T) {
+		for i := 0; i < 2; i++ {
+			k := fmt.Sprintf("key%d", i)
+			v := fmt.Sprintf("value%d", i)
+			for j := 0; j < 500; j++ {
+				rdb.LPush(ctx, k, v)
+				rdb.LRange(ctx, k, 0, 1)
+			}
+			time.Sleep(time.Second)
+		}
+
+		r := FindInfoEntry(t, "rocksdb", "put_per_sec")
+		require.Greater(t, MustAtoi(t, r), 0)
+		r = FindInfoEntry(t, "rocksdb", "get_per_sec")
+		require.Greater(t, MustAtoi(t, r), 0)
+		r = FindInfoEntry(t, "rocksdb", "seek_per_sec")
+		require.Greater(t, MustAtoi(t, r), 0)
+		r = FindInfoEntry(t, "rocksdb", "next_per_sec")
+		require.Greater(t, MustAtoi(t, r), 0)
+	})
+
+	t.Run("get bgsave information by INFO", func(t *testing.T) {
+		require.Equal(t, "0", FindInfoEntry(t, "persistence", "bgsave_in_progress"))
+		require.Equal(t, "-1", FindInfoEntry(t, "persistence", "last_bgsave_time"))
+		require.Equal(t, "ok", FindInfoEntry(t, "persistence", "last_bgsave_status"))
+		require.Equal(t, "-1", FindInfoEntry(t, "persistence", "last_bgsave_time_sec"))
+
+		r := rdb.Do(ctx, "bgsave")
+		v, err := r.Text()
+		require.NoError(t, err)
+		require.Equal(t, "OK", v)
+
+		require.Eventually(t, func() bool {
+			e := MustAtoi(t, FindInfoEntry(t, "persistence", "bgsave_in_progress"))
+			return e == 0
+		}, 5*time.Second, 100*time.Millisecond)
+
+		lastBgsaveTime := MustAtoi(t, FindInfoEntry(t, "persistence", "last_bgsave_time"))
+		require.Greater(t, lastBgsaveTime, 1640507660)
+		require.Equal(t, "ok", FindInfoEntry(t, "persistence", "last_bgsave_status"))
+		lastBgsaveTimeSec := MustAtoi(t, FindInfoEntry(t, "persistence", "last_bgsave_time_sec"))
+		require.GreaterOrEqual(t, lastBgsaveTimeSec, 0)
+		require.Less(t, lastBgsaveTimeSec, 3)
+	})
+}
diff --git a/tests/gocase/util/server.go b/tests/gocase/util/server.go
new file mode 100644
index 0000000..1b15572
--- /dev/null
+++ b/tests/gocase/util/server.go
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 util
+
+import (
+	"context"
+	"fmt"
+	"net"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"testing"
+	"time"
+
+	"github.com/go-redis/redis/v9"
+	"github.com/stretchr/testify/require"
+)
+
+type KvrocksServer struct {
+	t    *testing.T
+	cmd  *exec.Cmd
+	addr net.Addr
+
+	clean func()
+}
+
+func (s *KvrocksServer) NewClient() *redis.Client {
+	return redis.NewClient(&redis.Options{Addr: s.addr.String()})
+}
+
+func (s *KvrocksServer) Close() {
+	require.NoError(s.t, s.cmd.Process.Kill())
+	require.EqualError(s.t, s.cmd.Wait(), "signal: killed")
+	s.clean()
+}
+
+func StartServer(t *testing.T, configs map[string]string) (*KvrocksServer, error) {
+	b := os.Getenv("KVROCKS_BIN_PATH")
+	cmd := exec.Command(b)
+
+	addr, err := findFreePort()
+	if err != nil {
+		return nil, err
+	}
+	configs["bind"] = addr.IP.String()
+	configs["port"] = fmt.Sprintf("%d", addr.Port)
+
+	dir := os.Getenv("GO_CASE_WORKSPACE")
+	require.NoError(t, err)
+	dir, err = os.MkdirTemp(dir, "Server-*")
+	require.NoError(t, err)
+	configs["dir"] = dir
+
+	f, err := os.Create(filepath.Join(dir, "kvrocks.conf"))
+	if err != nil {
+		return nil, err
+	}
+
+	for k := range configs {
+		_, err := f.WriteString(fmt.Sprintf("%s %s\n", k, configs[k]))
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	cmd.Args = append(cmd.Args, "-c", f.Name())
+
+	stdout, err := os.Create(filepath.Join(dir, "stdout"))
+	require.NoError(t, err)
+	cmd.Stdout = stdout
+	stderr, err := os.Create(filepath.Join(dir, "stderr"))
+	require.NoError(t, err)
+	cmd.Stderr = stderr
+
+	if err := cmd.Start(); err != nil {
+		return nil, err
+	}
+
+	c := redis.NewClient(&redis.Options{Addr: addr.String()})
+	defer func() { require.NoError(t, c.Close()) }()
+	require.Eventually(t, func() bool {
+		return c.Ping(context.Background()).Err() == nil
+	}, time.Minute, time.Second)
+
+	return &KvrocksServer{
+		t:    t,
+		cmd:  cmd,
+		addr: addr,
+		clean: func() {
+			require.NoError(t, stdout.Close())
+			require.NoError(t, stderr.Close())
+		},
+	}, nil
+}
+
+func findFreePort() (*net.TCPAddr, error) {
+	addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
+	if err != nil {
+		return nil, err
+	}
+	lis, err := net.ListenTCP("tcp", addr)
+	defer func() { _ = lis.Close() }()
+	return lis.Addr().(*net.TCPAddr), nil
+}
diff --git a/tests/gocase/workspace/.gitignore b/tests/gocase/workspace/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/tests/gocase/workspace/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/tests/tcl/tests/test_helper.tcl b/tests/tcl/tests/test_helper.tcl
index 8d07885..b037aa5 100644
--- a/tests/tcl/tests/test_helper.tcl
+++ b/tests/tcl/tests/test_helper.tcl
@@ -56,7 +56,6 @@ set ::all_tests {
     unit/introspection
     unit/limits
     unit/geo
-    unit/command
     unit/config
     unit/scripting
     integration/slotmigrate
diff --git a/tests/tcl/tests/unit/command.tcl b/tests/tcl/tests/unit/command.tcl
deleted file mode 100644
index 5d3da15..0000000
--- a/tests/tcl/tests/unit/command.tcl
+++ /dev/null
@@ -1,85 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you 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.
-
-start_server {tags {"command"}} {
-    test {kvrocks has 180 commands currently} {
-        r command count
-    } {180}
-
-    test {acquire GET command info by COMMAND INFO} {
-        set e [lindex [r command info get] 0]
-        assert_equal [llength $e] 6
-        assert_equal [lindex $e 0] get
-        assert_equal [lindex $e 1] 2
-        assert_equal [lindex $e 2] {readonly}
-        assert_equal [lindex $e 3] 1
-        assert_equal [lindex $e 4] 1
-        assert_equal [lindex $e 5] 1
-    }
-
-    test {COMMAND - command entry length check} {
-        set e [lindex [r command] 0]
-        assert_equal [llength $e] 6
-    }
-
-    test {get keys of commands by COMMAND GETKEYS} {
-        assert_equal {test} [r command getkeys get test]
-        assert_equal {test test2} [r command getkeys mget test test2]
-        assert_equal {test} [r command getkeys zadd test 1 m1]
-    }
-
-    test {get rocksdb ops by COMMAND INFO} {
-        for {set i 0} {$i < 2} {incr i} {
-            for {set j 0} {$j < 500} {incr j} {
-                r lpush key$i value$i
-                r lrange key$i 0 1
-            }
-            after 1000
-        }
-
-        set put_qps [s put_per_sec]
-        set get_qps [s get_per_sec]
-        set seek_qps [s seek_per_sec]
-        set next_qps [s next_per_sec]
-
-        assert {$put_qps > 0}
-        assert {$get_qps > 0}
-        assert {$seek_qps > 0}
-        # prev_per_sec is almost the same as next_per_sec
-        assert {$next_qps > 0}
-    }
-
-    test {get bgsave information from INFO command} {
-        assert_equal 0 [s bgsave_in_progress]
-        assert_equal -1 [s last_bgsave_time]
-        assert_equal ok [s last_bgsave_status]
-        assert_equal -1 [s last_bgsave_time_sec]
-
-        assert_equal {OK} [r bgsave]
-        wait_for_condition 100 500 {
-            [s bgsave_in_progress] == 0
-        } else {
-            fail "Fail to bgsave"
-        }
-
-        set last_bgsave_time [s last_bgsave_time]
-        assert {$last_bgsave_time > 1640507660}
-        assert_equal ok [s last_bgsave_status]
-        set last_bgsave_time_sec [s last_bgsave_time_sec]
-        assert {$last_bgsave_time_sec < 3 && $last_bgsave_time_sec >= 0}
-    }
-}
diff --git a/tools/ci/licenserc.yml b/tools/ci/licenserc.yml
index ccf4bb1..0f0325f 100644
--- a/tools/ci/licenserc.yml
+++ b/tools/ci/licenserc.yml
@@ -24,11 +24,10 @@ header:
     - '**/CMakeLists.txt'
     - '**/*.cc'
     - '**/*.cmake'
+    - '**/*.go'
     - '**/*.h'
     - '**/*.py'
     - '**/*.sh'
     - '**/*.tcl'
     - '**/*.yml'
     - '**/*.yaml'
-  paths-ignore:
-    - 'external/'
\ No newline at end of file