2019-10-26 07:34:29 +02:00
|
|
|
package psql
|
|
|
|
|
|
|
|
import (
|
2020-02-10 07:45:37 +01:00
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
2019-10-26 07:34:29 +02:00
|
|
|
"log"
|
|
|
|
"os"
|
2020-02-10 07:45:37 +01:00
|
|
|
"strings"
|
2019-10-26 07:34:29 +02:00
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/dosco/super-graph/qcode"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
errNotExpected = "Generated SQL did not match what was expected"
|
2020-02-10 07:45:37 +01:00
|
|
|
headerMarker = "=== RUN"
|
|
|
|
commentMarker = "---"
|
2019-10-26 07:34:29 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
qcompile *qcode.Compiler
|
|
|
|
pcompile *Compiler
|
2020-02-10 07:45:37 +01:00
|
|
|
expected map[string][]string
|
2019-10-26 07:34:29 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
var err error
|
|
|
|
|
|
|
|
qcompile, err = qcode.NewCompiler(qcode.Config{
|
|
|
|
Blocklist: []string{
|
|
|
|
"secret",
|
|
|
|
"password",
|
|
|
|
"token",
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("user", "product", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
|
|
|
Columns: []string{"id", "name", "price", "users", "customers"},
|
|
|
|
Filters: []string{
|
|
|
|
"{ price: { gt: 0 } }",
|
|
|
|
"{ price: { lt: 8 } }",
|
|
|
|
},
|
|
|
|
},
|
2019-10-30 07:30:31 +01:00
|
|
|
Insert: qcode.InsertConfig{
|
|
|
|
Presets: map[string]string{
|
|
|
|
"user_id": "$user_id",
|
|
|
|
"created_at": "now",
|
|
|
|
"updated_at": "now",
|
|
|
|
},
|
|
|
|
},
|
2019-10-26 07:34:29 +02:00
|
|
|
Update: qcode.UpdateConfig{
|
|
|
|
Filters: []string{"{ user_id: { eq: $user_id } }"},
|
2019-10-30 07:30:31 +01:00
|
|
|
Presets: map[string]string{"updated_at": "now"},
|
2019-10-26 07:34:29 +02:00
|
|
|
},
|
|
|
|
Delete: qcode.DeleteConfig{
|
|
|
|
Filters: []string{
|
|
|
|
"{ price: { gt: 0 } }",
|
|
|
|
"{ price: { lt: 8 } }",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("anon", "product", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
|
|
|
Columns: []string{"id", "name"},
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("anon1", "product", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
|
|
|
Columns: []string{"id", "name", "price"},
|
|
|
|
DisableFunctions: true,
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("user", "users", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
|
|
|
Columns: []string{"id", "full_name", "avatar", "email", "products"},
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("bad_dude", "users", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
2019-10-27 06:52:48 +01:00
|
|
|
Filters: []string{"false"},
|
|
|
|
DisableFunctions: true,
|
2019-10-26 07:34:29 +02:00
|
|
|
},
|
|
|
|
Insert: qcode.InsertConfig{
|
|
|
|
Filters: []string{"false"},
|
|
|
|
},
|
|
|
|
Update: qcode.UpdateConfig{
|
|
|
|
Filters: []string{"false"},
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("user", "mes", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
|
|
|
Columns: []string{"id", "full_name", "avatar"},
|
|
|
|
Filters: []string{
|
|
|
|
"{ id: { eq: $user_id } }",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
2019-11-28 07:25:46 +01:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2019-11-28 07:25:46 +01:00
|
|
|
err = qcompile.AddRole("user", "customers", qcode.TRConfig{
|
2019-10-26 07:34:29 +02:00
|
|
|
Query: qcode.QueryConfig{
|
|
|
|
Columns: []string{"id", "email", "full_name", "products"},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2020-02-02 07:43:09 +01:00
|
|
|
schema := getTestSchema()
|
2019-10-26 07:34:29 +02:00
|
|
|
|
|
|
|
vars := NewVariables(map[string]string{
|
2019-11-21 08:14:12 +01:00
|
|
|
"admin_account_id": "5",
|
2019-10-26 07:34:29 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
pcompile = NewCompiler(Config{
|
|
|
|
Schema: schema,
|
|
|
|
Vars: vars,
|
|
|
|
})
|
|
|
|
|
2020-02-10 07:45:37 +01:00
|
|
|
expected = make(map[string][]string)
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2020-02-10 07:45:37 +01:00
|
|
|
b, err := ioutil.ReadFile("tests.sql")
|
2019-10-26 07:34:29 +02:00
|
|
|
if err != nil {
|
2020-02-10 07:45:37 +01:00
|
|
|
log.Fatal(err)
|
2019-10-26 07:34:29 +02:00
|
|
|
}
|
2020-02-10 07:45:37 +01:00
|
|
|
text := string(b)
|
|
|
|
lines := strings.Split(text, "\n")
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2020-02-10 07:45:37 +01:00
|
|
|
var h string
|
|
|
|
|
|
|
|
for _, v := range lines {
|
|
|
|
switch {
|
|
|
|
case strings.HasPrefix(v, headerMarker):
|
|
|
|
h = strings.TrimSpace(v[len(headerMarker):])
|
|
|
|
|
|
|
|
case strings.HasPrefix(v, commentMarker):
|
|
|
|
break
|
|
|
|
|
|
|
|
default:
|
|
|
|
v := strings.TrimSpace(v)
|
|
|
|
if len(v) != 0 {
|
|
|
|
expected[h] = append(expected[h], v)
|
|
|
|
}
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
}
|
2020-02-10 07:45:37 +01:00
|
|
|
os.Exit(m.Run())
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2020-02-10 07:45:37 +01:00
|
|
|
func compileGQLToPSQL(t *testing.T, gql string, vars Variables, role string) {
|
|
|
|
generateTestFile := false
|
|
|
|
|
|
|
|
if generateTestFile {
|
|
|
|
var sqlStmts []string
|
|
|
|
|
|
|
|
for i := 0; i < 100; i++ {
|
|
|
|
qc, err := qcompile.Compile([]byte(gql), role)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, sqlB, err := pcompile.CompileEx(qc, vars)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
sql := string(sqlB)
|
|
|
|
|
|
|
|
match := false
|
|
|
|
for _, s := range sqlStmts {
|
|
|
|
if sql == s {
|
|
|
|
match = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !match {
|
|
|
|
s := string(sql)
|
|
|
|
sqlStmts = append(sqlStmts, s)
|
|
|
|
fmt.Println(s)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
|
2020-02-10 07:45:37 +01:00
|
|
|
for i := 0; i < 200; i++ {
|
|
|
|
qc, err := qcompile.Compile([]byte(gql), role)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
_, sqlStmt, err := pcompile.CompileEx(qc, vars)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
failed := true
|
|
|
|
|
|
|
|
for _, sql := range expected[t.Name()] {
|
|
|
|
if string(sqlStmt) == sql {
|
|
|
|
failed = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if failed {
|
|
|
|
fmt.Println(string(sqlStmt))
|
|
|
|
t.Fatal(errNotExpected)
|
|
|
|
}
|
|
|
|
}
|
2019-10-26 07:34:29 +02:00
|
|
|
}
|