diff options
Diffstat (limited to 'tests/papod.go')
-rw-r--r-- | tests/papod.go | 1437 |
1 files changed, 1403 insertions, 34 deletions
diff --git a/tests/papod.go b/tests/papod.go index 5f07b43..aa16ded 100644 --- a/tests/papod.go +++ b/tests/papod.go @@ -2,11 +2,15 @@ package papod import ( "bufio" + "crypto/rand" "database/sql" "errors" "fmt" + "io" "os" + "reflect" "strings" + "time" "golite" "guuid" @@ -15,6 +19,18 @@ import ( +func mknstring(n int) string { + buffer := make([]byte, n) + _, err := io.ReadFull(rand.Reader, buffer) + g.TErrorIf(err) + return string(buffer) +} + +func mkstring() string { + return mknstring(32) +} + + func test_defaultPrefix() { g.TestStart("defaultPrefix") @@ -23,26 +39,80 @@ func test_defaultPrefix() { }) } -func test_tryRollback() { +func test_serialized() { // FIXME } -func test_inTx() { +func test_execSerialized() { // FIXME } +func test_tryRollback() { + g.TestStart("tryRollback()") + + myErr := errors.New("bottom error") + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + defer db.Close() + + + g.Testing("the error is propagated if rollback doesn't fail", func() { + tx, err := db.Begin() + g.TErrorIf(err) + + err = tryRollback(tx, myErr) + g.TAssertEqual(err, myErr) + }) + + g.Testing("a wrapped error when rollback fails", func() { + tx, err := db.Begin() + g.TErrorIf(err) + + err = tx.Commit() + g.TErrorIf(err) + + err = tryRollback(tx, myErr) + g.TAssertEqual(reflect.DeepEqual(err, myErr), false) + g.TAssertEqual(errors.Is(err, myErr), true) + }) +} + +func test_inTx() { + g.TestStart("inTx()") + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + defer db.Close() + + + g.Testing("when fn() errors, we propagate it", func() { + myErr := errors.New("to be propagated") + err := inTx(db, func(tx *sql.Tx) error { + return myErr + }) + g.TAssertEqual(err, myErr) + }) + + g.Testing("on nil error we get nil", func() { + err := inTx(db, func(tx *sql.Tx) error { + return nil + }) + g.TErrorIf(err) + }) +} + func test_createTables() { - return g.TestStart("createTables()") - db, err := sql.Open(golite.DriverName, ":memory:") + db, err := sql.Open(golite.DriverName, golite.InMemory) g.TErrorIf(err) defer db.Close() g.Testing("tables exist afterwards", func() { const tmpl_read = ` - SELECT id FROM "%s_events" LIMIT 1; + SELECT id FROM "%s_channel_events" LIMIT 1; ` qRead := fmt.Sprintf(tmpl_read, defaultPrefix) @@ -65,49 +135,1062 @@ func test_createTables() { }) } +func test_createUserStmt() { + g.TestStart("createUserStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + g.TErrorIf(createUserErr) + defer g.SomeFnError( + createUserClose, + db.Close, + ) + + + g.Testing("userID's must be unique", func() { + newUser := newUserT{ + uuid: guuid.New(), + } + + _, err1 := createUser(newUser) + _, err2 := createUser(newUser) + g.TErrorIf(err1) + g.TAssertEqual( + err2.(golite.Error).ExtendedCode, + golite.ErrConstraintUnique, + ) + }) + + g.Testing("a new user starts without a pictureID", func() { + newUser := newUserT{ + uuid: guuid.New(), + } + + user, err := createUser(newUser) + g.TErrorIf(err) + g.TAssertEqual(user.pictureID == nil, true) + }) + + g.Testing("the database fills default and generated values", func() { + newUser := newUserT{ + uuid: guuid.New(), + username: "the username", + displayName: "the display name", + } + + user, err := createUser(newUser) + g.TErrorIf(err) + + g.TAssertEqual(user.id == 0, false) + g.TAssertEqual(user.timestamp == time.Time{}, false) + g.TAssertEqual(user.uuid, newUser.uuid) + g.TAssertEqual(user.username, "the username") + g.TAssertEqual(user.displayName, "the display name") + }) + + g.Testing("users can have duplicate names and usernames", func() { + username := mkstring() + displayName := mkstring() + + newUser1 := newUserT{ + uuid: guuid.New(), + username: username, + displayName: displayName, + } + + newUser2 := newUserT{ + uuid: guuid.New(), + username: username, + displayName: displayName, + } + + _, err1 := createUser(newUser1) + _, err2 := createUser(newUser2) + g.TErrorIf(err1) + g.TErrorIf(err2) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + createUserClose(), + createUserClose(), + createUserClose(), + )) + }) +} + +func test_userByUUIDStmt() { + g.TestStart("userByUUIDStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + userByUUID, userByUUIDClose, userByUUIDErr := userByUUIDStmt(db, prefix) + deleteUser, deleteUserClose, deleteUserErr := deleteUserStmt(db, prefix) + g.TErrorIf(g.SomeError( + createUserErr, + deleteUserErr, + userByUUIDErr, + )) + defer g.SomeFnError( + createUserClose, + deleteUserClose, + userByUUIDClose, + db.Close, + ) + + + g.Testing("when a user doesn't exist, we get sql.ErrNoRows", func() { + _, err := userByUUID(guuid.New()) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("after creating, we can retrieve the user", func() { + newUser := newUserT{ + uuid: guuid.New(), + username: mkstring(), + displayName: mkstring(), + } + + user1, err := createUser(newUser) + g.TErrorIf(err) + + user2, err := userByUUID(newUser.uuid) + g.TErrorIf(err) + + g.TAssertEqual(user2.uuid, newUser.uuid) + g.TAssertEqual(user2.username, newUser.username) + g.TAssertEqual(user2.displayName, newUser.displayName) + g.TAssertEqual(user2.pictureID == nil, true) + + g.TAssertEqual(user2, user1) + }) + + g.Testing("we can't retrieve a user once deleted",func() { + newUser := newUserT{ + uuid: guuid.New(), + } + + _, err := createUser(newUser) + g.TErrorIf(err) + + _, err = userByUUID(newUser.uuid) + g.TErrorIf(err) + + err = deleteUser(newUser.uuid) + g.TErrorIf(err) + + _, err = userByUUID(newUser.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + userByUUIDClose(), + userByUUIDClose(), + userByUUIDClose(), + )) + }) +} + +func test_updateUserStmt() { + g.TestStart("updateUserStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + userByUUID, userByUUIDClose, userByUUIDErr := userByUUIDStmt(db, prefix) + updateUser, updateUserClose, updateUserErr := updateUserStmt(db, prefix) + deleteUser, deleteUserClose, deleteUserErr := deleteUserStmt(db, prefix) + g.TErrorIf(g.SomeError( + createUserErr, + userByUUIDErr, + updateUserErr, + deleteUserErr, + )) + defer g.SomeFnError( + createUserClose, + userByUUIDClose, + updateUserClose, + deleteUserClose, + db.Close, + ) + + create := func() userT { + newUser := newUserT{ + uuid: guuid.New(), + username: mkstring(), + displayName: mkstring(), + } + + user, err := createUser(newUser) + g.TErrorIf(err) + + return user + } + + + g.Testing("a user needs to exist to be updated", func() { + virtualUser := userT{ + id: 1234, + } + + g.TAssertEqual(updateUser(virtualUser), sql.ErrNoRows) + }) + + g.Testing("after updating, fetching gives us the newer data", func() { + newUser := newUserT{ + uuid: guuid.New(), + username: "first username", + displayName: "first display name", + } + + user1, err := createUser(newUser) + g.TErrorIf(err) + + g.TAssertEqual(user1.username, newUser.username) + g.TAssertEqual(user1.displayName, newUser.displayName) + + + user2 := user1 + user2.username = "second username" + user2.displayName = "second display name" + + err = updateUser(user2) + g.TErrorIf(err) + + g.TAssertEqual(user2.id, user1.id) + g.TAssertEqual(user2.timestamp, user1.timestamp) + g.TAssertEqual(user2.uuid, user1.uuid) + + + user3, err := userByUUID(user2.uuid) + g.TErrorIf(err) + + g.TAssertEqual(user3, user2) + g.TAssertEqual(user3.username, "second username") + g.TAssertEqual(user3.displayName, "second display name") + }) + + g.Testing("can't update a deleted user", func() { + user := create() + + err = deleteUser(user.uuid) + g.TErrorIf(err) + + err = updateUser(user) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("we can add (and remove) a picture to the user", func() { + user1 := create() + g.TAssertEqual(user1.pictureID == nil, true) + + pictureID := guuid.New() + user2 := user1 + user2.pictureID = &pictureID + err = updateUser(user2) + g.TErrorIf(err) + g.TAssertEqual(user2.pictureID == nil, false) + + user3, err := userByUUID(user1.uuid) + g.TErrorIf(err) + g.TAssertEqual(user3.pictureID == nil, false) + g.TAssertEqual(user3, user2) + + user4 := user3 + user4.pictureID = nil + err = updateUser(user4) + g.TErrorIf(err) + + user5, err := userByUUID(user1.uuid) + g.TErrorIf(err) + g.TAssertEqual(user5.pictureID == nil, true) + g.TAssertEqual(user5, user4) + }) + + g.Testing("we can't update the timestamp or uuid", func() { + user1 := create() + + user2 := user1 + user2.timestamp = user2.timestamp.Add(time.Minute * 1) + user2.uuid = guuid.New() + err = updateUser(user2) + g.TErrorIf(err) + + user3, err := userByUUID(user1.uuid) + g.TErrorIf(err) + g.TAssertEqual(user3, user1) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + updateUserClose(), + updateUserClose(), + updateUserClose(), + )) + }) +} + +func test_deleteUserStmt() { + g.TestStart("deleteUserStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + deleteUser, deleteUserClose, deleteUserErr := deleteUserStmt(db, prefix) + g.TErrorIf(g.SomeError( + createUserErr, + deleteUserErr, + )) + defer g.SomeFnError( + createUserClose, + deleteUserClose, + ) + + + g.Testing("a user needs to exist to be deleted", func() { + err := deleteUser(guuid.New()) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("error if deleted more than once", func() { + newUser := newUserT{ + uuid: guuid.New(), + } + + _, err := createUser(newUser) + g.TErrorIf(err) + + err1 := deleteUser(newUser.uuid) + err2 := deleteUser(newUser.uuid) + g.TErrorIf(err1) + g.TAssertEqual(err2, sql.ErrNoRows) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + deleteUserClose(), + deleteUserClose(), + deleteUserClose(), + )) + }) +} + func test_addNetworkStmt() { - return + return // FIXME g.TestStart("addNetworkStmt()") const ( prefix = defaultPrefix ) - db, err := sql.Open(golite.DriverName, ":memory:") + db, err := sql.Open(golite.DriverName, golite.InMemory) g.TErrorIf(err) g.TErrorIf(createTables(db, prefix)) + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + deleteUser, deleteUserClose, deleteUserErr := deleteUserStmt(db, prefix) addNetwork, addNetworkClose, addNetworkErr := addNetworkStmt(db, prefix) - g.TErrorIf(addNetworkErr) + g.TErrorIf(g.SomeError( + createUserErr, + deleteUserErr, + addNetworkErr, + )) defer g.SomeFnError( + createUserClose, + deleteUserClose, addNetworkClose, ) + create := func() userT { + newUser := newUserT{ + uuid: guuid.New(), + } + + user, err := createUser(newUser) + g.TErrorIf(err) + + return user + } + + + g.Testing("a user can create a newtwork", func() { + creator := create() + + newNetwork := newNetworkT{ + uuid: guuid.New(), + name: "the network name", + description: "the network description", + type_: NetworkType_Unlisted, + } + + network, err := addNetwork(creator, newNetwork) + g.TErrorIf(err) + + g.TAssertEqual(network.id == 0, false) + g.TAssertEqual(network.timestamp == time.Time{}, false) + g.TAssertEqual(network.uuid, newNetwork.uuid) + g.TAssertEqual(network.createdBy, creator.uuid) + g.TAssertEqual(network.name, "the network name") + g.TAssertEqual(network.description, "the network description") + g.TAssertEqual(network.type_, NetworkType_Unlisted) + }) + + g.Testing("the creator needs to exist", func() { + newNetwork := newNetworkT{ + uuid: guuid.New(), + } + + virtualUser := userT{ + uuid: guuid.New(), + } + + _, err := addNetwork(virtualUser, newNetwork) + g.TAssertEqual( + err.(golite.Error).ExtendedCode, + golite.ErrConstraintNotNull, + ) + }) g.Testing("we can't add the same network twice", func() { - // FIXME + creator := create() + + newNetwork := newNetworkT{ + uuid: guuid.New(), + name: mkstring(), + } + + _, err1 := addNetwork(creator, newNetwork) + _, err2 := addNetwork(creator, newNetwork) + g.TErrorIf(err1) + g.TAssertEqual( + err2.(golite.Error).ExtendedCode, + golite.ErrConstraintUnique, + ) }) g.Testing("a user can create multiple networks", func() { - userID := guuid.New() - newNetwork := newNetworkT{} + creator := create() + + newNetwork1 := newNetworkT{ + uuid: guuid.New(), + } + newNetwork2 := newNetworkT{ + uuid: guuid.New(), + } - network, err := addNetwork(userID, newNetwork) + network1, err1 := addNetwork(creator, newNetwork1) + network2, err2 := addNetwork(creator, newNetwork2) + g.TErrorIf(err1) + g.TErrorIf(err2) + + g.TAssertEqual(network1.createdBy, creator.uuid) + g.TAssertEqual(network2.createdBy, creator.uuid) + }) + + g.Testing("a deleted user can't create a network", func() { + creator := create() + + newNetwork1 := newNetworkT{ + uuid: guuid.New(), + } + newNetwork2 := newNetworkT{ + uuid: guuid.New(), + } + + _, err := addNetwork(creator, newNetwork1) g.TErrorIf(err) - g.TAssertEqual(network.createdBy, userID) + err = deleteUser(creator.uuid) + g.TErrorIf(err) + _, err = addNetwork(creator, newNetwork2) + g.TAssertEqual( + err.(golite.Error).ExtendedCode, + golite.ErrConstraintNotNull, + ) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + addNetworkClose(), + addNetworkClose(), + addNetworkClose(), + )) }) } -func test_addChannelStmt() { +func test_getNetworkStmt() { + return // FIXME + g.TestStart("getNetworkStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + deleteUser, deleteUserClose, deleteUserErr := deleteUserStmt(db, prefix) + addNetwork, addNetworkClose, addNetworkErr := addNetworkStmt(db, prefix) + getNetwork, getNetworkClose, getNetworkErr := getNetworkStmt(db, prefix) + addMember, addMemberClose, addMemberErr := addMemberStmt(db, prefix) + dropMember, dropMemberClose, dropMemberErr := dropMemberStmt(db, prefix) + g.TErrorIf(g.SomeError( + createUserErr, + deleteUserErr, + addNetworkErr, + getNetworkErr, + addMemberErr, + dropMemberErr, + )) + defer g.SomeFnError( + createUserClose, + deleteUserClose, + addNetworkClose, + getNetworkClose, + addMemberClose, + dropMemberClose, + ) + + create := func() userT { + newUser := newUserT{ + uuid: guuid.New(), + } + + user, err := createUser(newUser) + g.TErrorIf(err) + + return user + } + + add := func(user userT, type_ NetworkType) networkT { + newNetwork := newNetworkT{ + uuid: guuid.New(), + type_: type_, + } + + network, err := addNetwork(user, newNetwork) + g.TErrorIf(err) + + return network + } + + + g.Testing("what we get is the same that was created", func() { + creator := create() + network1 := add(creator, NetworkType_Public) + + network2, err := getNetwork(creator, network1.uuid) + g.TErrorIf(err) + g.TAssertEqual(network2, network1) + }) + + g.Testing("a network needs to exist", func() { + _, err := getNetwork(create(), guuid.New()) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("the probing user needs to exist", func() { + creator := create() + network := add(creator, NetworkType_Public) + + virtualUser := userT{ + id: 1234, + } + + _, err := getNetwork(creator, network.uuid) + g.TErrorIf(err) + + _, err = getNetwork(virtualUser, network.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("the probing user can see any public network", func() { + creator := create() + user := create() + network := add(creator, NetworkType_Public) + + network1, err1 := getNetwork(creator, network.uuid) + network2, err2 := getNetwork(user, network.uuid) + g.TErrorIf(err1) + g.TErrorIf(err2) + g.TAssertEqual(network1, network) + g.TAssertEqual(network2, network) + }) + + g.Testing("the probing user sees the given unlisted network", func() { + creator := create() + user := create() + network := add(creator, NetworkType_Unlisted) + + network1, err1 := getNetwork(creator, network.uuid) + network2, err2 := getNetwork(user, network.uuid) + g.TErrorIf(err1) + g.TErrorIf(err2) + g.TAssertEqual(network1, network) + g.TAssertEqual(network2, network) + }) + + g.Testing("the probing user can't see a private network", func() { + creator := create() + user := create() + network := add(creator, NetworkType_Private) + + _, err1 := getNetwork(creator, network.uuid) + _, err2 := getNetwork(user, network.uuid) + g.TErrorIf(err1) + g.TAssertEqual(err2, sql.ErrNoRows) + }) + + g.Testing("the probing user must be a member to see it", func() { + creator := create() + member := create() + network := add(creator, NetworkType_Private) + newMember := newMemberT{ + userID: member.uuid, + } + + _, err := addMember(creator, network, newMember) + g.TErrorIf(err) + + network1, err1 := getNetwork(creator, network.uuid) + network2, err2 := getNetwork(member, network.uuid) + g.TErrorIf(err1) + g.TErrorIf(err2) + g.TAssertEqual(network1, network) + g.TAssertEqual(network2, network) + }) + + g.Testing("we can get the network if the creator was deleted", func() { + creator := create() + member := create() + network := add(creator, NetworkType_Public) + newMember := newMemberT{ + userID: member.uuid, + } + + _, err := addMember(creator, network, newMember) + g.TErrorIf(err) + + network1, err := getNetwork(creator, network.uuid) + g.TErrorIf(err) + + err = deleteUser(creator.uuid) + g.TErrorIf(err) + + network2, err := getNetwork(member, network.uuid) + g.TErrorIf(err) + g.TAssertEqual(network2, network1) + }) + + g.Testing("a deleted creator can't get a network", func() { + creator := create() + network := add(creator, NetworkType_Public) + + _, err := getNetwork(creator, network.uuid) + g.TErrorIf(err) + + err = deleteUser(creator.uuid) + g.TErrorIf(err) + + _, err = getNetwork(creator, network.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("a deleted user can't get a public network", func() { + user := create() + network := add(create(), NetworkType_Public) + + _, err := getNetwork(user, network.uuid) + g.TErrorIf(err) + + err = deleteUser(user.uuid) + g.TErrorIf(err) + + _, err = getNetwork(user, network.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("a deleted member can't get a private network", func() { + creator := create() + member := create() + network := add(creator, NetworkType_Private) + + _, err := getNetwork(member, network.uuid) + g.TErrorIf(err) + + err = deleteUser(member.uuid) + g.TErrorIf(err) + + _, err = getNetwork(member, network.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("a removed member can't get a private network", func() { + creator := create() + member := create() + network := add(creator, NetworkType_Private) + newMember := newMemberT{ + userID: member.uuid, + } + + _, err := getNetwork(member, network.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + + _, err = addMember(creator, network, newMember) + g.TErrorIf(err) + + _, err = getNetwork(member, network.uuid) + g.TErrorIf(err) + + err = dropMember(creator, member.uuid) + g.TErrorIf(err) + + _, err = getNetwork(member, network.uuid) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + getNetworkClose(), + getNetworkClose(), + getNetworkClose(), + )) + }) +} + +func test_networkEach() { + // FIXME +} + +func test_networksStmt() { + /* + FIXME + g.TestStart("networksStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + addNetwork, addNetworkClose, addNetworkErr := addNetworkStmt(db, prefix) + networks, networksClose, networksErr := networksStmt(db, prefix) + g.TErrorIf(g.SomeError( + addNetworkErr, + networksErr, + )) + defer g.SomeFnError( + addNetworkClose, + networksClose, + db.Close, + ) + + nets := func(user userT) []networkT { + rows, err := networks(user) + g.TErrorIf(err) + + networkList := []networkT{} + err = networkEach(rows, func(network networkT) error { + networkList = append(networkList, network) + return nil + }) + g.TErrorIf(err) + + return networkList + } + + + g.Testing("when there are no networks, we get none", func() { + // FIXME + }) + + g.Testing("if we have only private networks, we also get none", func() { + // FIXME + }) + + g.Testing("we can get a list of public networks", func() { + // FIXME + }) + + g.Testing("a member user can see their's private networks", func() { + // FIXME + }) + + g.Testing("unlisted networks aren't shown", func() { + // FIXME + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + networksClose(), + networksClose(), + networksClose(), + )) + }) + */ +} + +func test_setNetworkStmt() { return // FIXME + g.TestStart("setNetworkStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + createUser, createUserClose, createUserErr := createUserStmt(db, prefix) + addNetwork, addNetworkClose, addNetworkErr := addNetworkStmt(db, prefix) + getNetwork, getNetworkClose, getNetworkErr := getNetworkStmt(db, prefix) + setNetwork, setNetworkClose, setNetworkErr := setNetworkStmt(db, prefix) + g.TErrorIf(g.SomeError( + createUserErr, + addNetworkErr, + getNetworkErr, + setNetworkErr, + )) + defer g.SomeFnError( + createUserClose, + addNetworkClose, + getNetworkClose, + setNetworkClose, + db.Close, + ) + + create := func() userT { + newUser := newUserT{ + uuid: guuid.New(), + } + + user, err := createUser(newUser) + g.TErrorIf(err) + + return user + } + + add := func(user userT) networkT { + newNetwork := newNetworkT{ + uuid: guuid.New(), + } + + network, err := addNetwork(user, newNetwork) + g.TErrorIf(err) + + return network + } + + + g.Testing("a network needs to exist to be updated", func() { + creator := create() + virtualNetwork := networkT{ + id: 1234, + } + + err := setNetwork(creator, virtualNetwork) + g.TAssertEqual(err, sql.ErrNoRows) + }) + + g.Testing("creator can change the network", func() { + // FIXME + }) + + g.Testing(`"network-settings-admin" can change the network`, func() { + // FIXME + }) + + g.Testing("ex-admin creator looses ability to change it", func() { + // FIXME + }) + + g.Testing("ex-member creator looses ability to change it", func() { + // FIXME + }) + + g.Testing("unauthorized users can't change the network", func() { + creator := create() + member := create() + network := add(creator) + + network.name = "member can't set the name" + err := setNetwork(member, network) + g.TAssertEqual(err, "403") + }) + + g.Testing("after setting, getting gives us the newer data", func() { + creator := create() + network1 := add(creator) + + network2 := network1 + network2.name = "first network name" + network2.description = "first network description" + network2.type_ = NetworkType_Private + + err := setNetwork(creator, network2) + g.TErrorIf(err) + + network3, err := getNetwork(creator, network1.uuid) + g.TErrorIf(err) + g.TAssertEqual(network3, network2) + }) + + g.Testing("the uuid, timestamp or creator never changes", func() { + creator := create() + network1 := add(creator) + + network2 := network1 + network2.uuid = guuid.New() + network2.timestamp = time.Time{} + network2.createdBy = guuid.New() + + err := setNetwork(creator, network2) + g.TErrorIf(err) + + network3, err := getNetwork(creator, network1.uuid) + g.TErrorIf(err) + g.TAssertEqual(network3, network1) + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + setNetworkClose(), + setNetworkClose(), + setNetworkClose(), + )) + }) +} + +func test_nipNetworkStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_addMemberStmt() { + /* + FIXME + g.TestStart("addMember()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + addNetwork, addNetworkClose, addNetworkErr := addNetworkStmt(db, prefix) + addMember, addMemberClose, addMemberErr := addMemberStmt(db, prefix) + g.TErrorIf(g.SomeError( + addNetworkErr, + addMemberErr, + )) + defer g.SomeFnError( + addNetworkClose, + addMemberClose, + ) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + addMemberClose(), + addMemberClose(), + addMemberClose(), + )) + }) + */ +} + +func test_showMemberStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_memberEach() { + // FIXME +} + +func test_membersStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_editMemberStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_dropMemberStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_addChannelStmt() { + // FIXME + return g.TestStart("addChannelStmt()") const ( prefix = defaultPrefix ) - db, err := sql.Open(golite.DriverName, ":memory:") + db, err := sql.Open(golite.DriverName, golite.InMemory) g.TErrorIf(err) g.TErrorIf(createTables(db, prefix)) @@ -142,33 +1225,272 @@ func test_addChannelStmt() { } // private channels one is not a part of doesn't show up // channels only from the same workspace + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) } -func test_initDB() { - g.TestStart("initDB()") +func test_channelEach() { + // FIXME +} - /* - q := new(liteq.Queue) - sql.Register("sqliteq", liteq.MakeDriver(q)) +func test_channelsStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_topicStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_endChannelStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_joinStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_partStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_nameEach() { + // FIXME +} + +func test_namesStmt() { + // FIXME + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + // FIXME + )) + }) +} + +func test_addEventStmt() { + return // FIXME + g.TestStart("addEventStmt()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + addEvent, addEventClose, addEventErr := addEventStmt(db, prefix) + g.TErrorIf(addEventErr) + defer g.SomeFnError( + addEventClose, + db.Close, + ) - db, err := sql.Open("sqliteq", "file:papod-test.db?mode=memory&cache=shared") - if err != nil { - panic(err) + + g.Testing("we can create new events", func() { + newEvent := newEventT{ + eventID: guuid.New(), + channelID: guuid.New(), + connectionID: guuid.New(), + type_: "user-message", + payload: "xablau", + } + + _, err := addEvent(newEvent) + g.TErrorIf(err) + }) + + g.Testing("eventID's must be unique", func() { + // FIXME + }) + + g.Testing("the database fills the generated values", func() { + const ( + type_ = "user-message" + payload = "the payload" + ) + eventID := guuid.New() + newEvent := newEventT{ + eventID: eventID, + channelID: guuid.New(), + connectionID: guuid.New(), + type_: type_, + payload: payload, + } + + event, err := addEvent(newEvent) + g.TErrorIf(err) + + g.TAssertEqual(event.id == 0, false) + g.TAssertEqual(event.timestamp == time.Time{}, false) + g.TAssertEqual(event.channelID == guuid.UUID{}, false) + g.TAssertEqual(event.connectionID == guuid.UUID{}, false) + g.TAssertEqual(event.uuid, eventID) + g.TAssertEqual(event.type_, type_) + g.TAssertEqual(event.payload, payload) + }) + + g.Testing("multiple messages can have the same connectionID", func() { + // FIXME + }) + + g.Testing("messages can be dupicated: same type and payload", func() { + // FIXME + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + addEventClose(), + addEventClose(), + addEventClose(), + )) + }) +} + +func test_eventEach() { + // FIXME +} + +func test_allAfterStmt() { + g.TestStart("allAfter()") + + const ( + prefix = defaultPrefix + ) + + db, err := sql.Open(golite.DriverName, golite.InMemory) + g.TErrorIf(err) + g.TErrorIf(createTables(db, prefix)) + + addChannel, addChannelClose, addChannelErr := addChannelStmt(db, prefix) + addEvent, addEventClose, addEventErr := addEventStmt(db, prefix) + allAfter, allAfterClose, allAfterErr := allAfterStmt(db, prefix) + g.TErrorIf(g.SomeError( + addChannelErr, + addEventErr, + allAfterErr, + )) + defer g.SomeFnError( + addChannelClose, + addEventClose, + allAfterClose, + db.Close, + ) + + channel := func(publicName string) channelT { + networkID := guuid.New() + newChannel := newChannelT{ + uuid: guuid.New(), + publicName: publicName, + } + + channel, err := addChannel(networkID, newChannel) + g.TErrorIf(err) + + return channel } - // defer db.Close() - *q, err = liteq.New(db) - if err != nil { - panic(err) + add := func(channelID guuid.UUID, type_ string, payload string) eventT { + newEvent := newEventT{ + eventID: guuid.New(), + channelID: channelID, + connectionID: guuid.New(), + type_: type_, + payload: payload, + } + + event, err := addEvent(newEvent) + g.TErrorIf(err) + + return event } - // defer q.Close() - // _, err = New(db, *q) - // _, err = initDB(db, - if err != nil { - panic(err) + all := func(eventID guuid.UUID) []eventT { + rows, err := allAfter(eventID) + g.TErrorIf(err) + + events := []eventT{} + err = eventEach(rows, func(event eventT) error { + events = append(events, event) + return nil + }) + g.TErrorIf(err) + + return events } - */ + + + g.Testing("after joining the channel, there are no events", func() { + ch := channel("#ch") + join := add(ch.uuid, "user-join", "fulano") + + expected := []eventT{ + add(ch.uuid, "user-join", "ciclano"), + add(ch.uuid, "user-join", "beltrano"), + add(ch.uuid, "user-message", "hi there"), + } + + given := all(join.uuid) + + g.TAssertEqual(given, expected) + }) + + g.Testing("we don't get events from other channels", func() { + }) + + g.Testing("as we change the reference point, the list changes", func() { + }) + + g.Testing("no error if closed more than once", func() { + g.TErrorIf(g.SomeError( + allAfterClose(), + allAfterClose(), + allAfterClose(), + )) + }) + // FIXME +} + +func test_initDB() { + // FIXME +} + +func test_queriesTclose() { + // FIXME } func test_splitOnCRLF() { @@ -607,11 +1929,29 @@ func test_parseMessage() { func dumpQueries() { queries := []struct{name string; fn func(string) queryT}{ { "createTables", createTablesSQL }, + { "createUser", createUserSQL }, + { "userByUUID", userByUUIDSQL }, + { "updateUser", updateUserSQL }, + { "deleteUser", deleteUserSQL }, { "addNetwork", addNetworkSQL }, + { "getNetwork", getNetworkSQL }, + { "networks", networksSQL }, + { "setNetwork", setNetworkSQL }, + { "nipNetwork", nipNetworkSQL }, + { "addMember", addMemberSQL }, + { "showMember", showMemberSQL }, + { "members", membersSQL }, + { "editMember", editMemberSQL }, + { "dropMember", dropMemberSQL }, { "addChannel", addChannelSQL }, { "channels", channelsSQL }, - { "allAfter", allAfterSQL }, + { "topic", topicSQL }, + { "endChannel", endChannelSQL }, + { "join", joinSQL }, + { "part", partSQL }, + { "names", namesSQL }, { "addEvent", addEventSQL }, + { "allAfter", allAfterSQL }, } for _, query := range queries { q := query.fn(defaultPrefix) @@ -631,12 +1971,41 @@ func MainTest() { g.Init() test_defaultPrefix() + test_serialized() + test_execSerialized() test_tryRollback() test_inTx() test_createTables() + test_createUserStmt() + test_userByUUIDStmt() + test_updateUserStmt() + test_deleteUserStmt() test_addNetworkStmt() + test_getNetworkStmt() + test_networkEach() + test_networksStmt() + test_setNetworkStmt() + test_nipNetworkStmt() + test_addMemberStmt() + test_showMemberStmt() + test_memberEach() + test_membersStmt() + test_editMemberStmt() + test_dropMemberStmt() test_addChannelStmt() + test_channelEach() + test_channelsStmt() + test_topicStmt() + test_endChannelStmt() + test_joinStmt() + test_partStmt() + test_nameEach() + test_namesStmt() + test_addEventStmt() + test_eventEach() + test_allAfterStmt() test_initDB() + test_queriesTclose() test_splitOnCRLF() test_splitOnRawMessage() test_parseMessageParams() |