package papod import ( "bufio" "database/sql" "errors" "fmt" "os" "strings" "golite" "guuid" g "gobang" ) func test_defaultPrefix() { g.TestStart("defaultPrefix") g.Testing("the defaultPrefix is valid", func() { g.TErrorIf(g.ValidateSQLTablePrefix(defaultPrefix)) }) } func test_tryRollback() { // FIXME } func test_inTx() { // FIXME } func test_createTables() { return g.TestStart("createTables()") db, err := sql.Open(golite.DriverName, ":memory:") g.TErrorIf(err) defer db.Close() g.Testing("tables exist afterwards", func() { const tmpl_read = ` SELECT id FROM "%s_events" LIMIT 1; ` qRead := fmt.Sprintf(tmpl_read, defaultPrefix) _, err := db.Exec(qRead) g.TErrorNil(err) err = createTables(db, defaultPrefix) g.TErrorIf(err) _, err = db.Exec(qRead) g.TErrorIf(err) }) g.Testing("we can do it multiple times", func() { g.TErrorIf(g.SomeError( createTables(db, defaultPrefix), createTables(db, defaultPrefix), createTables(db, defaultPrefix), )) }) } func test_addNetworkStmt() { return g.TestStart("addNetworkStmt()") const ( prefix = defaultPrefix ) db, err := sql.Open(golite.DriverName, ":memory:") g.TErrorIf(err) g.TErrorIf(createTables(db, prefix)) addNetwork, addNetworkClose, addNetworkErr := addNetworkStmt(db, prefix) g.TErrorIf(addNetworkErr) defer g.SomeFnError( addNetworkClose, ) g.Testing("we can't add the same network twice", func() { // FIXME }) g.Testing("a user can create multiple networks", func() { userID := guuid.New() newNetwork := newNetworkT{} network, err := addNetwork(userID, newNetwork) g.TErrorIf(err) g.TAssertEqual(network.createdBy, userID) }) } func test_addChannelStmt() { return // FIXME g.TestStart("addChannelStmt()") const ( prefix = defaultPrefix ) db, err := sql.Open(golite.DriverName, ":memory:") g.TErrorIf(err) g.TErrorIf(createTables(db, prefix)) addChannel, addChannelClose, addChannelErr := addChannelStmt(db, prefix) channels, channelsClose, channelsErr := channelsStmt(db, prefix) g.TErrorIf(g.SomeError( addChannelErr, channelsErr, )) defer g.SomeFnError( addChannelClose, channelsClose, db.Close, ) collect := func(workspaceID guuid.UUID) []channelT { rows, err := channels(workspaceID) g.TErrorIf(err) collected := []channelT{} err = channelEach(rows, func(channel channelT) error { collected = append(collected, channel) return nil }) g.TErrorIf(err) return collected } if true { g.TAssertEqual(addChannel, collect) } // private channels one is not a part of doesn't show up // channels only from the same workspace } func test_initDB() { g.TestStart("initDB()") /* q := new(liteq.Queue) sql.Register("sqliteq", liteq.MakeDriver(q)) db, err := sql.Open("sqliteq", "file:papod-test.db?mode=memory&cache=shared") if err != nil { panic(err) } // defer db.Close() *q, err = liteq.New(db) if err != nil { panic(err) } // defer q.Close() // _, err = New(db, *q) // _, err = initDB(db, if err != nil { panic(err) } */ } func test_splitOnCRLF() { type tableT struct{ input string expected []string } table := []tableT{ { "", nil, }, { "\r\n", []string{ "" }, }, { "abc\r\n", []string{ "abc" }, }, { "abc\r\n ", []string{ "abc" }, }, { "abc\r\n \r\n", []string{ "abc", " " }, }, { " \r\n \r\n", []string{ " ", " " }, }, { "aaa\r\nbbb\r\nccc\r\n", []string{ "aaa", "bbb", "ccc" }, }, { "\r\nsplit \r \n CRLF\r\n\r\n", []string{ "", "split \r \n CRLF", "" }, }, } for _, entry := range table { var given []string scanner := bufio.NewScanner(strings.NewReader(entry.input)) scanner.Split(splitOnCRLF) for scanner.Scan() { given = append(given, scanner.Text()) } err := scanner.Err() g.TErrorIf(err) g.TAssertEqual(given, entry.expected) } } func test_splitOnRawMessage() { type tableT struct{ input string expected []string } table := []tableT{ { "first message\r\nsecond message\r\n", []string{ "first message", "second message" }, }, { "message 1\r\n\r\nmessage 2\r\n\r\nignored", []string{ "message 1", "message 2" }, }, } for _, entry := range table { var given []string scanner := bufio.NewScanner(strings.NewReader(entry.input)) scanner.Split(splitOnRawMessage) for scanner.Scan() { given = append(given, scanner.Text()) } err := scanner.Err() g.TErrorIf(err) g.TAssertEqual(given, entry.expected) } } func test_parseMessageParams() { type tableT struct{ input string expected messageParamsT } table := []tableT{ { "", messageParamsT{ middle: []string { }, trailing: "", }, }, { " ", messageParamsT{ middle: []string { }, trailing: "", }, }, { " :", messageParamsT{ middle: []string { }, trailing: "", }, }, { " : ", messageParamsT{ middle: []string { }, trailing: " ", }, }, { ": ", messageParamsT{ middle: []string { ":" }, trailing: "", }, }, { ": ", messageParamsT{ middle: []string { ":" }, trailing: "", }, }, { " : ", messageParamsT{ middle: []string { }, trailing: " ", }, }, { " :", messageParamsT{ middle: []string { }, trailing: "", }, }, { " :", messageParamsT{ middle: []string { }, trailing: "", }, }, { "a", messageParamsT{ middle: []string { "a" }, trailing: "", }, }, { "ab", messageParamsT{ middle: []string { "ab" }, trailing: "", }, }, { "a b", messageParamsT{ middle: []string { "a", "b" }, trailing: "", }, }, { "a b c", messageParamsT{ middle: []string { "a", "b", "c" }, trailing: "", }, }, { "a b:c", messageParamsT{ middle: []string { "a", "b:c" }, trailing: "", }, }, { "a b:c:", messageParamsT{ middle: []string { "a", "b:c:" }, trailing: "", }, }, { "a b :c", messageParamsT{ middle: []string { "a", "b" }, trailing: "c", }, }, { "a b :c:", messageParamsT{ middle: []string { "a", "b" }, trailing: "c:", }, }, { "a b :c ", messageParamsT{ middle: []string { "a", "b" }, trailing: "c ", }, }, { "a b : c", messageParamsT{ middle: []string { "a", "b" }, trailing: " c", }, }, { "a b : c ", messageParamsT{ middle: []string { "a", "b" }, trailing: " c ", }, }, { "a b : c :", messageParamsT{ middle: []string { "a", "b" }, trailing: " c :", }, }, { "a b : c : ", messageParamsT{ middle: []string { "a", "b" }, trailing: " c : ", }, }, { "a b : c :d", messageParamsT{ middle: []string { "a", "b" }, trailing: " c :d", }, }, { "a b : c :d ", messageParamsT{ middle: []string { "a", "b" }, trailing: " c :d ", }, }, { "a b : c : d ", messageParamsT{ middle: []string { "a", "b" }, trailing: " c : d ", }, }, } for _, entry := range table { given := parseMessageParams(entry.input) g.TAssertEqual(given, entry.expected) } } func test_parseMessage() { type tableTOK struct{ input string expected messageT } tableOK := []tableTOK {{ "NICK joebloe ", messageT{ prefix: "", command: "NICK", params: messageParamsT{ middle: []string { "joebloe" }, trailing: "", }, raw: "NICK joebloe ", }, }, { "USER joebloe 0.0.0.0 joe :Joe Bloe", messageT{ prefix: "", command: "USER", params: messageParamsT{ middle: []string { "joebloe", "0.0.0.0", "joe", }, trailing: "Joe Bloe", }, raw: "USER joebloe 0.0.0.0 joe :Joe Bloe", }, }, { ":pre USER joebloe 0.0.0.0 joe :Joe Bloe", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { "joebloe", "0.0.0.0", "joe", }, trailing: "Joe Bloe", }, raw: ":pre USER joebloe 0.0.0.0 joe :Joe Bloe", }, }, { ":pre USER joebloe 0.0.0.0 joe : Joe Bloe ", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { "joebloe", "0.0.0.0", "joe", }, trailing: " Joe Bloe ", }, raw: ":pre USER joebloe 0.0.0.0 joe : Joe Bloe ", }, }, { ":pre USER joebloe: 0:0:0:1 joe::a: : Joe Bloe ", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { "joebloe:", "0:0:0:1", "joe::a:", }, trailing: " Joe Bloe ", }, raw: ":pre USER joebloe: 0:0:0:1 joe::a: : Joe Bloe ", }, }, { ":pre USER :Joe Bloe", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { }, trailing: "Joe Bloe", }, raw: ":pre USER :Joe Bloe", }, }, { ":pre USER : Joe Bloe", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { }, trailing: " Joe Bloe", }, raw: ":pre USER : Joe Bloe", }, }, { ":pre USER : Joe Bloe", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { }, trailing: " Joe Bloe", }, raw: ":pre USER : Joe Bloe", }, }, { ":pre USER : ", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { }, trailing: " ", }, raw: ":pre USER : ", }, }, { ":pre USER :", messageT{ prefix: "pre", command: "USER", params: messageParamsT{ middle: []string { }, trailing: "", }, raw: ":pre USER :", }, }} for _, entry := range tableOK { given, err := parseMessage(entry.input) g.TErrorIf(err) g.TAssertEqual(given, entry.expected) } type tableErrorT struct{ input string expected error } parseErr := errors.New("Can't parse message") tableError := []tableErrorT{ { ":pre", parseErr, }, { ": pre", parseErr, }, { ":pre N1CK", parseErr, }, } for _, entry := range tableError { _, given := parseMessage(entry.input) g.TAssertEqual(given, entry.expected) } } func dumpQueries() { queries := []struct{name string; fn func(string) queryT}{ { "createTables", createTablesSQL }, { "addNetwork", addNetworkSQL }, { "addChannel", addChannelSQL }, { "channels", channelsSQL }, { "allAfter", allAfterSQL }, { "addEvent", addEventSQL }, } for _, query := range queries { q := query.fn(defaultPrefix) fmt.Printf("\n-- %s.sql:", query.name) fmt.Printf("\n-- write:%s\n", q.write) fmt.Printf("\n-- read:%s\n", q.read) } } func MainTest() { if os.Getenv("TESTING_DUMP_SQL_QUERIES") != "" { dumpQueries() return } g.Init() test_defaultPrefix() test_tryRollback() test_inTx() test_createTables() test_addNetworkStmt() test_addChannelStmt() test_initDB() test_splitOnCRLF() test_splitOnRawMessage() test_parseMessageParams() test_parseMessage() }