diff --git a/cmd/debug_test.go b/cmd/debug_test.go index 5fcc05ff9978..cb9c422bc132 100644 --- a/cmd/debug_test.go +++ b/cmd/debug_test.go @@ -20,47 +20,29 @@ import ( "fmt" "testing" - . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/require" ) func TestDebug(t *testing.T) { mountTemp(t, nil, nil, nil) defer umountTemp(t) - Convey("TestDebug", t, func() { - Convey("Mount point does not exist", func() { - mp := "/jfs/test/mp" - So(Main([]string{"", "debug", mp}), ShouldNotBeNil) - }) - Convey("Directory is not a mount point", func() { - mp := "./" - So(Main([]string{"", "debug", mp}), ShouldNotBeNil) - }) - - }) - - Convey("TestDebug_OutDir", t, func() { - Convey("Specify a file as out dir", func() { - So(Main([]string{"", "debug", "--out-dir", "./debug_test.go", testMountPoint}), ShouldNotBeNil) - }) - }) - - Convey("TestDebug_LogArg", t, func() { - cases := []struct { - arg string - val string - }{ - {"--log /var/log/jfs.log", "/var/log/jfs.log"}, - {"--log=/var/log/jfs.log", "/var/log/jfs.log"}, - {"--log = /var/log/jfs.log", "/var/log/jfs.log"}, - {"--log= /var/log/jfs.log", "/var/log/jfs.log"}, - {"--log =/var/log/jfs.log", "/var/log/jfs.log"}, - {"--log /var/log/jfs.log", "/var/log/jfs.log"}, - } - for i, c := range cases { - Convey(fmt.Sprintf("valid log arg %d", i), func() { - So(logArg.FindStringSubmatch(c.arg)[2] == c.val, ShouldBeTrue) - }) - } - }) + require.NotNil(t, Main([]string{"", "debug", "/jfs/test/mp"}), "mount point does not exist") + require.NotNil(t, Main([]string{"", "debug", "./"}), "directory is not a mount point") + require.NotNil(t, Main([]string{"", "debug", "--out-dir", "./debug_test.go", testMountPoint}), "specify a file as out dir") + + cases := []struct { + arg string + val string + }{ + {"--log /var/log/jfs.log", "/var/log/jfs.log"}, + {"--log=/var/log/jfs.log", "/var/log/jfs.log"}, + {"--log = /var/log/jfs.log", "/var/log/jfs.log"}, + {"--log= /var/log/jfs.log", "/var/log/jfs.log"}, + {"--log =/var/log/jfs.log", "/var/log/jfs.log"}, + {"--log /var/log/jfs.log", "/var/log/jfs.log"}, + } + for i, c := range cases { + require.True(t, logArg.FindStringSubmatch(c.arg)[2] == c.val, fmt.Sprintf("valid log arg %d", i)) + } } diff --git a/cmd/gc_test.go b/cmd/gc_test.go index cbb8862056fd..83c2c7412a93 100644 --- a/cmd/gc_test.go +++ b/cmd/gc_test.go @@ -23,6 +23,9 @@ import ( "strings" "testing" "time" + + "github.com/juicedata/juicefs/pkg/utils" + "github.com/stretchr/testify/require" ) func writeSmallBlocks(mountDir string) error { @@ -88,6 +91,8 @@ func TestGc(t *testing.T) { } } + os.Setenv("JFS_GC_SKIPPEDTIME", "0") + defer os.Unsetenv("JFS_GC_SKIPPEDTIME") t.Logf("JFS_GC_SKIPPEDTIME is %s", os.Getenv("JFS_GC_SKIPPEDTIME")) leaked := filepath.Join(dataDir, "0", "0", "123456789_0_1048576") @@ -98,9 +103,7 @@ func TestGc(t *testing.T) { t.Fatalf("gc delete failed: %s", err) } - if _, err := os.Stat(leaked); err == nil { - t.Fatalf("gc delete didn't delete the leaked data") - } + require.False(t, utils.Exists(leaked)) if err := Main([]string{"", "gc", testMeta}); err != nil { t.Fatalf("gc failed: %s", err) diff --git a/cmd/info_test.go b/cmd/info_test.go index dca16271dad4..fe9bcb23a7b8 100644 --- a/cmd/info_test.go +++ b/cmd/info_test.go @@ -23,46 +23,42 @@ import ( "testing" "github.com/agiledragon/gomonkey/v2" - . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/require" ) func TestInfo(t *testing.T) { - Convey("TestInfo", t, func() { - Convey("TestInfo", func() { - tmpFile, err := os.CreateTemp("/tmp", "") - if err != nil { - t.Fatalf("create temporary file: %s", err) - } - defer tmpFile.Close() - defer os.Remove(tmpFile.Name()) - mountTemp(t, nil, nil, nil) - defer umountTemp(t) - // mock os.Stdout - patches := gomonkey.ApplyGlobalVar(os.Stdout, *tmpFile) - defer patches.Reset() + tmpFile, err := os.CreateTemp("/tmp", "") + if err != nil { + t.Fatalf("create temporary file: %s", err) + } + defer tmpFile.Close() + defer os.Remove(tmpFile.Name()) + mountTemp(t, nil, nil, nil) + defer umountTemp(t) + // mock os.Stdout + patches := gomonkey.ApplyGlobalVar(os.Stdout, *tmpFile) + defer patches.Reset() - if err = os.MkdirAll(fmt.Sprintf("%s/dir1", testMountPoint), 0777); err != nil { - t.Fatalf("mkdirAll failed: %s", err) - } - for i := 0; i < 10; i++ { - filename := fmt.Sprintf("%s/dir1/f%d.txt", testMountPoint, i) - if err = os.WriteFile(filename, []byte("test"), 0644); err != nil { - t.Fatalf("write file failed: %s", err) - } - } + if err = os.MkdirAll(fmt.Sprintf("%s/dir1", testMountPoint), 0777); err != nil { + t.Fatalf("mkdirAll failed: %s", err) + } + for i := 0; i < 10; i++ { + filename := fmt.Sprintf("%s/dir1/f%d.txt", testMountPoint, i) + if err = os.WriteFile(filename, []byte("test"), 0644); err != nil { + t.Fatalf("write file failed: %s", err) + } + } - if err = Main([]string{"", "info", fmt.Sprintf("%s/dir1", testMountPoint), "--strict"}); err != nil { - t.Fatalf("info failed: %s", err) - } - content, err := os.ReadFile(tmpFile.Name()) - if err != nil { - t.Fatalf("read file failed: %s", err) - } - replacer := strings.NewReplacer("\n", "", " ", "") - res := replacer.Replace(string(content)) - answer := fmt.Sprintf("%s/dir1: inode: 2 files: 10 dirs: 1 length: 40 Bytes size: 44.00 KiB (45056 Bytes) path: /dir1", testMountPoint) - answer = replacer.Replace(answer) - So(res, ShouldEqual, answer) - }) - }) + if err = Main([]string{"", "info", fmt.Sprintf("%s/dir1", testMountPoint), "--strict"}); err != nil { + t.Fatalf("info failed: %s", err) + } + content, err := os.ReadFile(tmpFile.Name()) + if err != nil { + t.Fatalf("read file failed: %s", err) + } + replacer := strings.NewReplacer("\n", "", " ", "") + res := replacer.Replace(string(content)) + answer := fmt.Sprintf("%s/dir1: inode: 2 files: 10 dirs: 1 length: 40 Bytes size: 44.00 KiB (45056 Bytes) path: /dir1", testMountPoint) + answer = replacer.Replace(answer) + require.Equal(t, answer, res) } diff --git a/cmd/mount_test.go b/cmd/mount_test.go index ccc70d064892..2c964022341f 100644 --- a/cmd/mount_test.go +++ b/cmd/mount_test.go @@ -19,8 +19,6 @@ package cmd import ( "context" "fmt" - "github.com/juicedata/juicefs/pkg/version" - "github.com/stretchr/testify/assert" "io" "net/http" "net/url" @@ -28,15 +26,19 @@ import ( "reflect" "runtime" "strings" + "sync" "testing" "time" + "github.com/juicedata/juicefs/pkg/version" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/agiledragon/gomonkey/v2" "github.com/juicedata/juicefs/pkg/meta" "github.com/juicedata/juicefs/pkg/utils" "github.com/juicedata/juicefs/pkg/vfs" "github.com/redis/go-redis/v9" - . "github.com/smartystreets/goconvey/convey" "github.com/urfave/cli/v2" ) @@ -46,54 +48,50 @@ const testVolume = "test" // gomonkey may encounter the problem of insufficient permissions under mac, please solve it by viewing this link https://github.com/agiledragon/gomonkey/issues/70 func Test_exposeMetrics(t *testing.T) { - Convey("Test_exposeMetrics", t, func() { - Convey("Test_exposeMetrics", func() { - addr := "redis://127.0.0.1:6379/12" - client := meta.NewClient(addr, nil) - format := &meta.Format{ - Name: "test", - BlockSize: 4096, - Capacity: 1 << 30, - DirStats: true, - } - _ = client.Init(format, true) - var appCtx *cli.Context - stringPatches := gomonkey.ApplyMethod(reflect.TypeOf(appCtx), "String", func(_ *cli.Context, arg string) string { - switch arg { - case "metrics": - return "127.0.0.1:9567" - case "consul": - return "127.0.0.1:8500" - case "custom-labels": - return "key1:value1" - default: - return "" - } - }) - isSetPatches := gomonkey.ApplyMethod(reflect.TypeOf(appCtx), "IsSet", func(_ *cli.Context, arg string) bool { - switch arg { - case "custom-labels": - return true - default: - return false - } - }) - defer stringPatches.Reset() - defer isSetPatches.Reset() - ResetHttp() - registerer, registry := wrapRegister(appCtx, "test", "test") - metricsAddr := exposeMetrics(appCtx, registerer, registry) - client.InitMetrics(registerer) - vfs.InitMetrics(registerer) - u := url.URL{Scheme: "http", Host: metricsAddr, Path: "/metrics"} - resp, err := http.Get(u.String()) - So(err, ShouldBeNil) - all, err := io.ReadAll(resp.Body) - So(err, ShouldBeNil) - So(string(all), ShouldNotBeBlank) - So(string(all), ShouldContainSubstring, `key1="value1"`) - }) + addr := "redis://127.0.0.1:6379/12" + client := meta.NewClient(addr, nil) + format := &meta.Format{ + Name: "test", + BlockSize: 4096, + Capacity: 1 << 30, + DirStats: true, + } + _ = client.Init(format, true) + var appCtx *cli.Context + stringPatches := gomonkey.ApplyMethod(reflect.TypeOf(appCtx), "String", func(_ *cli.Context, arg string) string { + switch arg { + case "metrics": + return "127.0.0.1:9567" + case "consul": + return "127.0.0.1:8500" + case "custom-labels": + return "key1:value1" + default: + return "" + } + }) + isSetPatches := gomonkey.ApplyMethod(reflect.TypeOf(appCtx), "IsSet", func(_ *cli.Context, arg string) bool { + switch arg { + case "custom-labels": + return true + default: + return false + } }) + defer stringPatches.Reset() + defer isSetPatches.Reset() + ResetHttp() + registerer, registry := wrapRegister(appCtx, "test", "test") + metricsAddr := exposeMetrics(appCtx, registerer, registry) + client.InitMetrics(registerer) + vfs.InitMetrics(registerer) + u := url.URL{Scheme: "http", Host: metricsAddr, Path: "/metrics"} + resp, err := http.Get(u.String()) + require.Nil(t, err) + all, err := io.ReadAll(resp.Body) + require.Nil(t, err) + require.NotEmpty(t, all) + require.Contains(t, string(all), `key1="value1"`) } func ResetHttp() { @@ -107,7 +105,14 @@ func resetTestMeta() *redis.Client { // using Redis return rdb } +var mountLock sync.Mutex + func mountTemp(t *testing.T, bucket *string, extraFormatOpts []string, extraMountOpts []string) { + // wait for last mount exit + for !mountLock.TryLock() { + time.Sleep(100 * time.Millisecond) + } + _ = resetTestMeta() testDir := t.TempDir() if bucket != nil { @@ -130,6 +135,7 @@ func mountTemp(t *testing.T, bucket *string, extraFormatOpts []string, extraMoun mountArgs = append(mountArgs, extraMountOpts...) } go func() { + defer mountLock.Unlock() if err := Main(mountArgs); err != nil { t.Errorf("mount failed: %s", err) } @@ -140,7 +146,7 @@ func mountTemp(t *testing.T, bucket *string, extraFormatOpts []string, extraMoun t.Fatalf("get file inode failed: %s", err) } if inode != 1 { - t.Fatalf("mount failed: inode of %s is not 1", testMountPoint) + t.Fatalf("mount failed: inode of %s got %d, expect 1", testMountPoint, inode) } else { t.Logf("mount %s success", testMountPoint) } @@ -206,6 +212,11 @@ func TestUmount(t *testing.T) { } func tryMountTemp(t *testing.T, bucket *string, extraFormatOpts []string, extraMountOpts []string) error { + // wait for last mount exit + for !mountLock.TryLock() { + time.Sleep(100 * time.Millisecond) + } + _ = resetTestMeta() testDir := t.TempDir() if bucket != nil { @@ -227,8 +238,10 @@ func tryMountTemp(t *testing.T, bucket *string, extraFormatOpts []string, extraM mountArgs = append(mountArgs, extraMountOpts...) } + os.Setenv("JFS_SUPERVISOR", "test") errChan := make(chan error, 1) go func() { + defer mountLock.Unlock() errChan <- Main(mountArgs) }() @@ -245,7 +258,7 @@ func tryMountTemp(t *testing.T, bucket *string, extraFormatOpts []string, extraM return fmt.Errorf("get file inode failed: %w", err) } if inode != 1 { - return fmt.Errorf("mount failed: inode of %s is not 1", testMountPoint) + return fmt.Errorf("mount failed: inode of %s is %d, expect 1", testMountPoint, inode) } t.Logf("mount %s success", testMountPoint) return nil diff --git a/cmd/status_test.go b/cmd/status_test.go index abad2906c210..9f611a7407ff 100644 --- a/cmd/status_test.go +++ b/cmd/status_test.go @@ -22,41 +22,35 @@ import ( "testing" "github.com/agiledragon/gomonkey/v2" - - . "github.com/smartystreets/goconvey/convey" ) func TestStatus(t *testing.T) { - Convey("TestStatus", t, func() { - Convey("TestStatus", func() { - tmpFile, err := os.CreateTemp("/tmp", "") - if err != nil { - t.Fatalf("create temporary file: %s", err) - } - defer tmpFile.Close() - defer os.Remove(tmpFile.Name()) - - mountTemp(t, nil, nil, nil) - defer umountTemp(t) - - // mock os.Stdout - patches := gomonkey.ApplyGlobalVar(os.Stdout, *tmpFile) - defer patches.Reset() - - if err = Main([]string{"", "status", testMeta}); err != nil { - t.Fatalf("status failed: %s", err) - } - content, err := os.ReadFile(tmpFile.Name()) - if err != nil { - t.Fatalf("read file failed: %s", err) - } - s := sections{} - if err = json.Unmarshal(content, &s); err != nil { - t.Fatalf("json unmarshal failed: %s", err) - } - if s.Setting.Name != testVolume || s.Setting.Storage != "file" { - t.Fatalf("setting is not as expected: %+v", s.Setting) - } - }) - }) + tmpFile, err := os.CreateTemp("/tmp", "") + if err != nil { + t.Fatalf("create temporary file: %s", err) + } + defer tmpFile.Close() + defer os.Remove(tmpFile.Name()) + + mountTemp(t, nil, nil, nil) + defer umountTemp(t) + + // mock os.Stdout + patches := gomonkey.ApplyGlobalVar(os.Stdout, *tmpFile) + defer patches.Reset() + + if err = Main([]string{"", "status", testMeta}); err != nil { + t.Fatalf("status failed: %s", err) + } + content, err := os.ReadFile(tmpFile.Name()) + if err != nil { + t.Fatalf("read file failed: %s", err) + } + s := sections{} + if err = json.Unmarshal(content, &s); err != nil { + t.Fatalf("json unmarshal failed: %s", err) + } + if s.Setting.Name != testVolume || s.Setting.Storage != "file" { + t.Fatalf("setting is not as expected: %+v", s.Setting) + } } diff --git a/go.mod b/go.mod index b9c79db1d13c..b777c9cb7754 100644 --- a/go.mod +++ b/go.mod @@ -57,7 +57,6 @@ require ( github.com/qiniu/go-sdk/v7 v7.15.0 github.com/redis/go-redis/v9 v9.0.2 github.com/sirupsen/logrus v1.9.3 - github.com/smartystreets/goconvey v1.7.2 github.com/stretchr/testify v1.8.4 github.com/studio-b12/gowebdav v0.0.0-20230203202212-3282f94193f2 github.com/tencentyun/cos-go-sdk-v5 v0.7.45 @@ -90,6 +89,7 @@ require ( require ( github.com/andybalholm/brotli v1.1.0 // indirect github.com/go-resty/resty/v2 v2.11.0 // indirect + github.com/smartystreets/goconvey v1.7.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect ) @@ -148,7 +148,6 @@ require ( github.com/google/readahead v0.0.0-20161222183148-eaceba169032 // indirect github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect github.com/googleapis/gax-go/v2 v2.7.1 // indirect - github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect github.com/gorilla/handlers v1.5.1 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/grafana/pyroscope-go/godeltaprof v0.1.6 @@ -168,7 +167,6 @@ require ( github.com/jcmturner/goidentity/v6 v6.0.1 // indirect github.com/jcmturner/rpc/v2 v2.0.3 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/jtolds/gls v4.20.0+incompatible // indirect github.com/klauspost/compress v1.17.7 // indirect github.com/klauspost/cpuid v1.3.1 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect @@ -217,7 +215,6 @@ require ( github.com/secure-io/sio-go v0.3.1 // indirect github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/smartystreets/assertions v1.2.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/stathat/consistent v1.0.0 // indirect github.com/syndtr/goleveldb v1.0.0 // indirect