package servicecontext import ( "context" "io" "os" "path/filepath" "testing" "time" "example.com/userService/internal/settings" "git.yuntuo.hk/k2safe/go-omni/database" "git.yuntuo.hk/k2safe/go-omni/logx" ) func TestStartupFailureAndIdempotentCleanup(t *testing.T) { if os.Getenv("USER_SERVICE_TEST_DATABASE") != "1" { t.Skip("isolated MySQL required") } t.Setenv("USER_SERVICE_API_TOKEN", "test-012345678901234567890123456789") t.Setenv("GO_OMNI_STORAGE_SIGNING_KEY", "test-012345678901234567890123456789") cfg, err := settings.Load("../../etc/config.yaml") if err != nil { t.Fatal(err) } observer, err := database.Open(context.Background(), cfg.Database) if err != nil { t.Fatal(err) } defer observer.Close() count := func() int { var n int if err := observer.QueryRow("SELECT COUNT(*) FROM information_schema.processlist WHERE USER=SUBSTRING_INDEX(CURRENT_USER(),'@',1) AND DB=DATABASE()").Scan(&n); err != nil { t.Fatal(err) } return n } baseline := count() cfg.Server.Log.File = "" cfg.Server.Log.Writer = io.Discard cfg.Server.Log.Rotation = logx.RotationConfig{} logger, err := logx.New(cfg.Server.Log) if err != nil { t.Fatal(err) } defer logger.Close() root := t.TempDir() file := filepath.Join(root, "notADirectory") if err = os.WriteFile(file, []byte("x"), 0600); err != nil { t.Fatal(err) } cfg.Storage.Root = file if c, err := New(context.Background(), logger, cfg); err == nil { c.Close() t.Fatal("invalid storage root accepted") } deadline := time.Now().Add(3 * time.Second) for count() != baseline { if time.Now().After(deadline) { t.Fatal("failed startup leaked MySQL connection") } time.Sleep(10 * time.Millisecond) } cfg.Storage.Root = filepath.Join(root, "files") c, err := New(context.Background(), logger, cfg) if err != nil { t.Fatal(err) } if err = c.Close(); err != nil { t.Fatal(err) } if err = c.Close(); err != nil { t.Fatal(err) } if err = c.DB.Ping(); err == nil { t.Fatal("closed application retained database") } if err = c.InitStorage(context.Background(), cfg.Storage); err == nil { t.Fatal("closed dependencies reopened storage") } }