Add test demonstrating race condition in autoCompleteSuggestions.sort()

Add TestAutocompleteSuggestions_ConcurrentSort to demonstrate the race
condition that occurs when sort() is called concurrently on the same
autoCompleteSuggestions instance. The test creates a suggestions object
with sample data and calls sort() from 10 concurrent goroutines.

When run with -race flag, this test fails with DATA RACE warnings,
showing concurrent reads and writes to the underlying slice arrays
during sorting operations.

This test demonstrates the bug reported in #4711.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Nathan Wallace
2025-11-16 16:17:40 -05:00
parent ed5bc425aa
commit a974f3360d

View File

@@ -1,8 +1,10 @@
package interactive
import (
"sync"
"testing"
"github.com/c-bata/go-prompt"
"github.com/stretchr/testify/assert"
"github.com/turbot/steampipe/v2/pkg/db/db_common"
"github.com/turbot/steampipe/v2/pkg/steampipeconfig"
@@ -31,3 +33,62 @@ func TestInitialiseSchemaAndTableSuggestions_NilClient(t *testing.T) {
c.initialiseSchemaAndTableSuggestions(connectionStateMap)
})
}
// TestAutocompleteSuggestions_ConcurrentSort tests that the sort() method
// can be called concurrently without data races.
// This is a regression test for bug #4711.
func TestAutocompleteSuggestions_ConcurrentSort(t *testing.T) {
// Create suggestions with some data to sort
suggestions := newAutocompleteSuggestions()
suggestions.schemas = []prompt.Suggest{
{Text: "schema2", Description: "Schema"},
{Text: "schema1", Description: "Schema"},
{Text: "schema3", Description: "Schema"},
}
suggestions.unqualifiedTables = []prompt.Suggest{
{Text: "table2", Description: "Table"},
{Text: "table1", Description: "Table"},
{Text: "table3", Description: "Table"},
}
suggestions.tablesBySchema = map[string][]prompt.Suggest{
"schema1": {
{Text: "schema1.table2", Description: "Table"},
{Text: "schema1.table1", Description: "Table"},
},
"schema2": {
{Text: "schema2.table2", Description: "Table"},
{Text: "schema2.table1", Description: "Table"},
},
}
suggestions.queriesByMod = map[string][]prompt.Suggest{
"mod1": {
{Text: "query2", Description: "Query"},
{Text: "query1", Description: "Query"},
},
"mod2": {
{Text: "query2", Description: "Query"},
{Text: "query1", Description: "Query"},
},
}
// Call sort() concurrently from multiple goroutines
// This should trigger the race detector if there's no synchronization
var wg sync.WaitGroup
numGoroutines := 10
for i := 0; i < numGoroutines; i++ {
wg.Add(1)
go func() {
defer wg.Done()
suggestions.sort()
}()
}
// Wait for all goroutines to complete
wg.Wait()
// Verify that data is still valid (not corrupted)
assert.Len(t, suggestions.schemas, 3)
assert.Len(t, suggestions.unqualifiedTables, 3)
assert.Len(t, suggestions.tablesBySchema, 2)
assert.Len(t, suggestions.queriesByMod, 2)
}