package cassandra import ( "fmt" "testing" "github.com/gocql/gocql" "github.com/stretchr/testify/assert" ) func TestIsSAISupported(t *testing.T) { tests := []struct { version string expected bool }{ {"5.0.0", true}, // 5.x 支援 {"5.1.2", true}, // 5.x 支援 {"6.0.0", true}, // 6.x 理論上也支援 {"4.0.8", false}, // 4.0.8 不支援 {"4.0.9", true}, // 4.0.9 支援 {"4.1.0", true}, // 4.1.0 支援 {"4.2.2", true}, // 4.2.2 支援 {"3.11.10", false}, // 3.x 不支援 {"3.0.0", false}, {"", false}, // 空字串,不支援 {"unknown", false}, // 無效格式 {"4", false}, // 缺 patch,不支援 {"4.0", false}, // 缺 patch,不支援 {"5", false}, // 缺 minor {"5.0", true}, // 5.0 預設支援 } for _, tt := range tests { t.Run(tt.version, func(t *testing.T) { result := isSAISupported(tt.version) assert.Equal(t, tt.expected, result, "version: %s", tt.version) }) } } // TestCassandraDB_Integration_TableDriven 使用 table-driven 方式整合測試 func TestCassandraDB_Integration_TableDriven(t *testing.T) { // 啟動 Cassandra container dbContainer, err := initCassandraContainer("5.0.4") defer func() { _ = dbContainer.Container.Terminate(dbContainer.Ctx) fmt.Println("[TEST] Container terminated") }() // 建立 CassandraDB 連線 hosts := []string{dbContainer.Host} db, err := NewCassandraDB( hosts, WithPort(dbContainer.Port), WithConsistency(gocql.One), WithNumConns(2), ) assert.NoError(t, err, "should success create CassandraDB") assert.NotNil(t, db, "db should not be nil") assert.NotNil(t, db.GetSession(), "get Session should not be nil") err = db.EnsureTable("CREATE KEYSPACE my_keyspace\nWITH replication = {\n 'class': 'SimpleStrategy',\n 'replication_factor': 1\n};\n") assert.NoError(t, err, "should success ensure table") // 注意:由於 Close 會關閉 session,因此請把測試 Close 的子案例放在所有使用 session 的子案例之後 tests := []struct { name string action func() error wantErr bool }{ { name: "ok", action: func() error { // 建立一個合法的資料表 (使用 IF NOT EXISTS 避免重複建立錯誤) schema := "CREATE TABLE IF NOT EXISTS my_keyspace.test (id uuid PRIMARY KEY, name text)" return db.EnsureTable(schema) }, wantErr: false, }, { name: "failed to ensure table since wrong schema", action: func() error { // 傳入無效的 CQL 語法,預期應回傳錯誤 schema := "CREATE TABLE invalid schema" return db.EnsureTable(schema) }, wantErr: true, }, { name: "GetSession 返回有效 Session", action: func() error { if db.GetSession().Session == nil { return fmt.Errorf("session is nil") } return nil }, wantErr: false, }, { name: "Close close Session", action: func() error { db.Close() // 無法直接驗證內部是否已關閉,但可避免再次使用 session 產生 panic return nil }, wantErr: false, }, } // 依序執行各子案例 for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { err := tc.action() if (err != nil) != tc.wantErr { t.Errorf("%s havs error = %v, wantErr %v", tc.name, err, tc.wantErr) } }) } } func TestCassandraDB_getReleaseVersion(t *testing.T) { type fields struct { Version string } tests := []struct { name string fields fields want string wantError bool }{ { name: "3", fields: fields{Version: "3.11"}, want: "3.11.19", wantError: false, }, { name: "5", fields: fields{Version: "5.0.4"}, want: "5.0.4", wantError: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { container, err := initCassandraContainer(tt.fields.Version) defer func() { _ = container.Container.Terminate(container.Ctx) fmt.Println("[TEST] Container terminated") }() if !tt.wantError { assert.NoError(t, err) // 建立 CassandraDB 連線 hosts := []string{container.Host} db, err := NewCassandraDB( hosts, WithPort(container.Port), WithConsistency(gocql.One), WithNumConns(2), ) assert.NoError(t, err) version, err := db.getReleaseVersion() assert.NoError(t, err) assert.Equal(t, version, tt.want) } }) } }