github.com/dkishere/pop/v6@v6.103.1/model_context_test.go (about) 1 package pop 2 3 import ( 4 "context" 5 "strings" 6 "testing" 7 "time" 8 9 "github.com/stretchr/testify/require" 10 ) 11 12 type ContextTable struct { 13 ID string `db:"id"` 14 Value string `db:"value"` 15 CreatedAt time.Time `db:"created_at"` 16 UpdatedAt time.Time `db:"updated_at"` 17 } 18 19 func (t ContextTable) TableName(ctx context.Context) string { 20 // This is singular on purpose! It will check if the TableName is properly 21 // Respected in slices as well. 22 prefix := ctx.Value("prefix").(string) 23 24 // PostgreSQL and CockroachDB support schemas which work like a prefix. For those cases, we use 25 // the schema to ensure that name normalization does not cause query problems. 26 // 27 // Since this works only for those two databases, we use underscore for the rest. 28 // 29 // While this schema is hardcoded, it would have been too difficult to add this special 30 // case to the migrations. 31 switch PDB.Dialect.Name() { 32 case nameCockroach: 33 fallthrough 34 case namePostgreSQL: 35 prefix = prefix + "." + prefix 36 } 37 return "context_prefix_" + prefix + "_table" 38 } 39 40 func Test_ModelContext(t *testing.T) { 41 if PDB == nil { 42 t.Skip("skipping integration tests") 43 } 44 45 t.Run("contextless", func(t *testing.T) { 46 r := require.New(t) 47 r.Panics(func() { 48 var c ContextTable 49 r.NoError(PDB.Create(&c)) 50 }, "panics if context prefix is not set") 51 }) 52 53 for _, prefix := range []string{"a", "b"} { 54 t.Run("prefix="+prefix, func(t *testing.T) { 55 r := require.New(t) 56 57 expected := ContextTable{ID: prefix, Value: prefix} 58 c := PDB.WithContext(context.WithValue(context.Background(), "prefix", prefix)) 59 r.NoError(c.Create(&expected)) 60 61 var actual ContextTable 62 r.NoError(c.Find(&actual, expected.ID)) 63 r.EqualValues(prefix, actual.Value) 64 r.EqualValues(prefix, actual.ID) 65 66 exists, err := c.Where("id = ?", actual.ID).Exists(new(ContextTable)) 67 r.NoError(err) 68 r.True(exists) 69 70 count, err := c.Where("id = ?", actual.ID).Count(new(ContextTable)) 71 r.NoError(err) 72 r.EqualValues(1, count) 73 74 expected.Value += expected.Value 75 r.NoError(c.Update(&expected)) 76 77 r.NoError(c.Find(&actual, expected.ID)) 78 r.EqualValues(prefix+prefix, actual.Value) 79 r.EqualValues(prefix, actual.ID) 80 81 var results []ContextTable 82 require.NoError(t, c.All(&results)) 83 84 require.NoError(t, c.First(&expected)) 85 require.NoError(t, c.Last(&expected)) 86 87 r.NoError(c.Destroy(&expected)) 88 }) 89 } 90 91 t.Run("prefix=unknown", func(t *testing.T) { 92 r := require.New(t) 93 c := PDB.WithContext(context.WithValue(context.Background(), "prefix", "unknown")) 94 err := c.Create(&ContextTable{ID: "unknown"}) 95 r.Error(err) 96 97 if !strings.Contains(err.Error(), "context_prefix_unknown") { // All other databases 98 t.Fatalf("Expected error to contain indicator that table does not exist but got: %s", err.Error()) 99 } 100 }) 101 102 t.Run("cache_busting", func(t *testing.T) { 103 r := require.New(t) 104 105 var expectedA, expectedB ContextTable 106 expectedA.ID = "expectedA" 107 expectedB.ID = "expectedB" 108 109 cA := PDB.WithContext(context.WithValue(context.Background(), "prefix", "a")) 110 r.NoError(cA.Create(&expectedA)) 111 112 cB := PDB.WithContext(context.WithValue(context.Background(), "prefix", "b")) 113 r.NoError(cB.Create(&expectedB)) 114 115 var actualA, actualB []ContextTable 116 r.NoError(cA.All(&actualA)) 117 r.NoError(cB.All(&actualB)) 118 119 r.Len(actualA, 1) 120 r.Len(actualB, 1) 121 122 r.NotEqual(actualA[0].ID, actualB[0].ID, "if these are equal context switching did not work") 123 }) 124 }