Browse Source

test: exercise session-owned executors and HTTP transaction IDs (#14)

Danilo Fragoso 11 hours ago
parent
commit
04a3b918f6

+ 2 - 1
pkg/executor/alter_table_test.go

@@ -67,7 +67,8 @@ func TestAlterTableAddColumnIfNotExistsConcurrent(t *testing.T) {
 		wg.Add(1)
 		go func() {
 			defer wg.Done()
-			if _, err := execSQL(e, "ALTER TABLE t ADD COLUMN IF NOT EXISTS c TEXT"); err != nil {
+			session := newExec(schema, table)
+			if _, err := execSQL(session, "ALTER TABLE t ADD COLUMN IF NOT EXISTS c TEXT"); err != nil {
 				t.Errorf("add column: %v", err)
 			}
 		}()

+ 2 - 0
pkg/executor/executor.go

@@ -130,6 +130,8 @@ func New(schema *storage.SchemaManager, table *storage.TableManager) *Executor {
 	return executor
 }
 
+// An Executor owns mutable session state and must not be used concurrently.
+// Use one executor per PostgreSQL connection or HTTP transaction/request.
 // NewSessionExecutor returns a new executor sharing the same schema and table
 // managers but with fresh per-executor state (transaction, subquery caches,
 // views). It is used to isolate concurrent requests that must not share mutable

+ 3 - 2
pkg/executor/rowid_cursor_test.go

@@ -143,13 +143,14 @@ func TestRowIDUniqueAndMonotonicUnderConcurrentInsert(t *testing.T) {
 		wg.Add(1)
 		go func(worker int) {
 			defer wg.Done()
+			session := newExec(schema, table)
 			for i := 0; i < perWorker; i++ {
 				id := strconv.Itoa(worker*perWorker + i + 1)
-				if _, err := execSQL(e, "INSERT INTO t (id, v) VALUES ("+id+", 'x')"); err != nil {
+				if _, err := execSQL(session, "INSERT INTO t (id, v) VALUES ("+id+", 'x')"); err != nil {
 					t.Errorf("insert %s: %v", id, err)
 					return
 				}
-				res, err := execSQL(e, "SELECT _rowid_ FROM t WHERE id = "+id)
+				res, err := execSQL(session, "SELECT _rowid_ FROM t WHERE id = "+id)
 				if err != nil {
 					t.Errorf("select %s: %v", id, err)
 					return

+ 13 - 2
pkg/httpserver/server_test.go

@@ -519,7 +519,11 @@ func TestTransactionEndpoints(t *testing.T) {
 	}
 
 	// Test COMMIT transaction
-	r = httptest.NewRequest(http.MethodPost, "/transaction/commit", nil)
+	body, err := json.Marshal(TransactionRequest{TransactionID: beginResp["transactionId"].(string)})
+	if err != nil {
+		t.Fatal(err)
+	}
+	r = httptest.NewRequest(http.MethodPost, "/transaction/commit", bytes.NewReader(body))
 	w = httptest.NewRecorder()
 	server.handleTransactionCommit(w, r)
 
@@ -537,9 +541,16 @@ func TestTransactionEndpoints(t *testing.T) {
 	r = httptest.NewRequest(http.MethodPost, "/transaction/begin", nil)
 	w = httptest.NewRecorder()
 	server.handleTransactionBegin(w, r)
+	if err := json.NewDecoder(w.Body).Decode(&beginResp); err != nil {
+		t.Fatal(err)
+	}
+	body, err = json.Marshal(TransactionRequest{TransactionID: beginResp["transactionId"].(string)})
+	if err != nil {
+		t.Fatal(err)
+	}
 
 	// Test ROLLBACK transaction
-	r = httptest.NewRequest(http.MethodPost, "/transaction/rollback", nil)
+	r = httptest.NewRequest(http.MethodPost, "/transaction/rollback", bytes.NewReader(body))
 	w = httptest.NewRecorder()
 	server.handleTransactionRollback(w, r)