Live video on the AT Protocol
1package statedb
2
3import (
4 "fmt"
5 "net/url"
6 "os"
7 "os/exec"
8 "strings"
9 "testing"
10 "time"
11
12 "github.com/google/uuid"
13 "github.com/stretchr/testify/require"
14 "gorm.io/driver/postgres"
15 "stream.place/streamplace/pkg/config"
16 "stream.place/streamplace/pkg/model"
17)
18
19var postgresURL string
20
21func TestMain(m *testing.M) {
22 postgresCommand := os.Getenv("STREAMPLACE_TEST_POSTGRES_COMMAND")
23 postgresURL = os.Getenv("STREAMPLACE_TEST_POSTGRES_URL")
24 if postgresCommand != "" {
25 // Start postgres process
26 fmt.Printf("Starting postgres process with command: %s\n", postgresCommand)
27 cmd := exec.Command("bash", "-c", postgresCommand)
28 err := cmd.Start()
29 if err != nil {
30 fmt.Printf("Failed to start postgres: %v\n", err)
31 os.Exit(1)
32 }
33
34 // Give postgres time to start up
35 time.Sleep(2 * time.Second)
36
37 // Run tests
38 exitCode := m.Run()
39
40 // Clean up postgres process
41 if cmd.Process != nil {
42 cmd2 := exec.Command("pkill", "postgres")
43 err := cmd2.Run()
44 if err != nil {
45 fmt.Printf("Failed to kill postgres: %v\n", err)
46 }
47 }
48
49 os.Exit(exitCode)
50 return
51 }
52 os.Exit(m.Run())
53}
54
55func makePostgresURL(t *testing.T) string {
56 u, err := url.Parse(postgresURL)
57 if err != nil {
58 panic(err)
59 }
60 uu, err := uuid.NewV7()
61 if err != nil {
62 panic(err)
63 }
64 dbName := fmt.Sprintf("test_%s", strings.ReplaceAll(uu.String(), "-", "_"))
65 u.Path = fmt.Sprintf("/%s", dbName)
66 t.Cleanup(func() {
67 u, err := url.Parse(postgresURL)
68 if err != nil {
69 panic(err)
70 }
71 u.Path = "/postgres"
72 rootDial := postgres.Open(u.String())
73
74 db, err := openDB(rootDial)
75 if err != nil {
76 t.Logf("Failed to open database: %v", err)
77 return
78 }
79
80 // Drop the test database
81 err = db.Exec(fmt.Sprintf("DROP DATABASE %s", dbName)).Error
82 if err != nil {
83 t.Logf("Failed to drop test database: %v", err)
84 }
85 })
86 return u.String()
87}
88
89func TestPostgresLocks(t *testing.T) {
90 if postgresURL == "" {
91 t.Skip("no postgres url, skipping postgres tests")
92 return
93 }
94 dburl := makePostgresURL(t)
95 cli := config.CLI{
96 DBURL: dburl,
97 }
98 mod, err := model.MakeDB(":memory:")
99 require.NoError(t, err)
100 state, err := MakeDB(&cli, nil, mod)
101 require.NoError(t, err)
102
103 unlock, err := state.GetNamedLock("test")
104 t.Log("got lock")
105 require.NoError(t, err)
106 require.NotNil(t, unlock)
107
108 shouldBeLocked := true
109
110 done := make(chan struct{})
111
112 go func() {
113 unlock2, err := state.GetNamedLock("test")
114 t.Log("got lock 2")
115 require.Equal(t, shouldBeLocked, false)
116 require.NoError(t, err)
117 require.NotNil(t, unlock2)
118 unlock2()
119 close(done)
120 }()
121
122 time.Sleep(1 * time.Second)
123
124 t.Log("unlocking")
125 shouldBeLocked = false
126 unlock()
127 t.Log("unlocked")
128
129 select {
130 case <-done:
131 case <-time.After(1 * time.Second):
132 require.Fail(t, "lock not released")
133 }
134 sqlDB, err := state.DB.DB()
135 require.NoError(t, err)
136
137 // Close
138 sqlDB.Close()
139}