// that correct results are returned in every goroutine. It's not 100% that this
// test would bring out a bug, but it's almost 100%.
//
// See https://github.com/mattn/go-sqlite3/issues/959#issuecomment-890283264
funcTest_ParallelOperationsInMemory(t*testing.T){
db:=mustCreateInMemoryDatabase()
deferdb.Close()
if_,err:=db.ExecuteStringStmt("CREATE TABLE foo (id INTEGER NOT NULL PRIMARY KEY, name TEXT)");err!=nil{
t.Fatalf("failed to create table: %s",err.Error())
}
if_,err:=db.ExecuteStringStmt("CREATE TABLE bar (id INTEGER NOT NULL PRIMARY KEY, name TEXT)");err!=nil{
t.Fatalf("failed to create table: %s",err.Error())
}
if_,err:=db.ExecuteStringStmt("CREATE TABLE qux (id INTEGER NOT NULL PRIMARY KEY, name TEXT)");err!=nil{
t.Fatalf("failed to create table: %s",err.Error())
}
// Confirm schema is as expected, when checked from same goroutine.
ifrows,err:=db.QueryStringStmt(`SELECT sql FROM sqlite_master`);err!=nil{
t.Fatalf("failed to query for schema after creation: %s",err.Error())
}else{
ifexp,got:=`[{"columns":["sql"],"types":["text"],"values":[["CREATE TABLE foo (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"],["CREATE TABLE bar (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"],["CREATE TABLE qux (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"]]}]`,asJSON(rows);exp!=got{
t.Fatalf("schema not as expected during after creation, exp %s, got %s",exp,got)
}
}
varexWgsync.WaitGroup
exWg.Add(3)
foo:=make(chantime.Time)
bar:=make(chantime.Time)
qux:=make(chantime.Time)
done:=make(chanbool)
ticker:=time.NewTicker(1*time.Millisecond)
gofunc(){
for{
select{
caset:=<-ticker.C:
foo<-t
bar<-t
qux<-t
case<-done:
close(foo)
close(bar)
close(qux)
return
}
}
}()
gofunc(){
deferexWg.Done()
forrangefoo{
if_,err:=db.ExecuteStringStmt(`INSERT INTO foo(id, name) VALUES(1, "fiona")`);err!=nil{
t.Logf("failed to insert records into foo: %s",err.Error())
}
}
}()
gofunc(){
deferexWg.Done()
forrangebar{
if_,err:=db.ExecuteStringStmt(`INSERT INTO bar(id, name) VALUES(1, "fiona")`);err!=nil{
t.Logf("failed to insert records into bar: %s",err.Error())
}
}
}()
gofunc(){
deferexWg.Done()
forrangequx{
if_,err:=db.ExecuteStringStmt(`INSERT INTO qux(id, name) VALUES(1, "fiona")`);err!=nil{
t.Logf("failed to insert records into qux: %s",err.Error())
}
}
}()
varqWgsync.WaitGroup
qWg.Add(3)
fori:=0;i<3;i++{
gofunc(jint){
deferqWg.Done()
varnint
for{
ifrows,err:=db.QueryStringStmt(`SELECT sql FROM sqlite_master`);err!=nil{
t.Logf("failed to query for schema during goroutine %d execution: %s",j,err.Error())
}else{
n++
ifexp,got:=`[{"columns":["sql"],"types":["text"],"values":[["CREATE TABLE foo (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"],["CREATE TABLE bar (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"],["CREATE TABLE qux (id INTEGER NOT NULL PRIMARY KEY, name TEXT)"]]}]`,asJSON(rows);exp!=got{
t.Logf("schema not as expected during goroutine execution, exp %s, got %s, after %d queries",exp,got,n)
}
}
ifn==500000{
break
}
}
}(i)
}
qWg.Wait()
close(done)
exWg.Wait()
}
// Test_TableCreationLoadRawInMemory tests for https://sqlite.org/forum/forumpost/d443fb0730