191 lines
5.5 KiB
Go
191 lines
5.5 KiB
Go
package shared
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.entityseven.com/rilaxik/pllist/internal/domain"
|
|
)
|
|
|
|
func TestCallbackID(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
data string
|
|
action CallbackAction
|
|
want int64
|
|
wantErr bool
|
|
}{
|
|
{name: "valid", data: "v1:open_list:42", action: ActionListOpen, want: 42},
|
|
{name: "wrong action", data: "v1:rename_list:42", action: ActionListOpen, wantErr: true},
|
|
{name: "wrong version", data: "v2:open_list:42", action: ActionListOpen, wantErr: true},
|
|
{name: "unversioned", data: "open_list:42", action: ActionListOpen, wantErr: true},
|
|
{name: "not a number", data: "v1:open_list:abc", action: ActionListOpen, wantErr: true},
|
|
{name: "zero", data: "v1:open_list:0", action: ActionListOpen, wantErr: true},
|
|
{name: "negative", data: "v1:open_list:-1", action: ActionListOpen, wantErr: true},
|
|
{name: "missing id", data: "v1:open_list", action: ActionListOpen, wantErr: true},
|
|
{name: "extra arg", data: "v1:open_list:42:1", action: ActionListOpen, wantErr: true},
|
|
{name: "too long", data: "v1:open_list:" + strings.Repeat("1", MaxCallbackDataLength), action: ActionListOpen, wantErr: true},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got, err := CallbackID(tt.data, tt.action)
|
|
if (err != nil) != tt.wantErr {
|
|
t.Fatalf("CallbackID() error = %v, wantErr %v", err, tt.wantErr)
|
|
}
|
|
if got != tt.want {
|
|
t.Fatalf("CallbackID() = %d, want %d", got, tt.want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestListDataRoundTrip(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
data string
|
|
action CallbackAction
|
|
}{
|
|
{name: "open", data: ListData(42), action: ActionListOpen},
|
|
{name: "rename", data: RenameListData(42), action: ActionListRename},
|
|
{name: "delete", data: DeleteListData(42), action: ActionListDelete},
|
|
{name: "delete yes", data: DeleteListYesData(42), action: ActionListDeleteYes},
|
|
{name: "shares", data: SharesData(42), action: ActionShareManage},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if !strings.HasPrefix(tt.data, "v1:") {
|
|
t.Fatalf("callback data is not versioned: %q", tt.data)
|
|
}
|
|
id, err := CallbackID(tt.data, tt.action)
|
|
if err != nil {
|
|
t.Fatalf("CallbackID(%q) error = %v", tt.data, err)
|
|
}
|
|
if id != 42 {
|
|
t.Fatalf("CallbackID(%q) = %d, want 42", tt.data, id)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPageCallbackRoundTrip(t *testing.T) {
|
|
data := PageData(42, 3)
|
|
listID, page, err := ParsePage(data)
|
|
if err != nil {
|
|
t.Fatalf("ParsePage(%q) error = %v", data, err)
|
|
}
|
|
if listID != 42 || page != 3 {
|
|
t.Fatalf("ParsePage(%q) = %d, %d", data, listID, page)
|
|
}
|
|
}
|
|
|
|
func TestPageCallbackRejectsBadData(t *testing.T) {
|
|
for _, data := range []string{
|
|
"v1:page",
|
|
"v1:page:42",
|
|
"v1:page:0:1",
|
|
"v1:page:42:0",
|
|
"v1:page:42:abc",
|
|
"v1:page:42:1:extra",
|
|
"page:42:1",
|
|
} {
|
|
if _, _, err := ParsePage(data); err == nil {
|
|
t.Fatalf("ParsePage(%q) accepted invalid data", data)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestShareCallbackRoundTrips(t *testing.T) {
|
|
for _, pending := range []bool{false, true} {
|
|
ref := ShareRef{ListID: 42, ShareID: 7, Pending: pending}
|
|
for _, tt := range []struct {
|
|
name string
|
|
data string
|
|
action CallbackAction
|
|
}{
|
|
{name: "view", data: ShareViewData(ref), action: ActionShareView},
|
|
{name: "revoke", data: ShareRevokeData(ref), action: ActionShareRevoke},
|
|
{name: "revoke yes", data: ShareRevokeYesData(ref), action: ActionShareRevokeYes},
|
|
} {
|
|
got, err := ParseShareRef(tt.data, tt.action)
|
|
if err != nil {
|
|
t.Fatalf("%s ParseShareRef(%q) error = %v", tt.name, tt.data, err)
|
|
}
|
|
if got != ref {
|
|
t.Fatalf("%s ParseShareRef(%q) = %+v, want %+v", tt.name, tt.data, got, ref)
|
|
}
|
|
}
|
|
|
|
got, role, err := ParseShareSet(ShareSetData(ref, domain.RoleReader))
|
|
if err != nil || role != domain.RoleReader || got != ref {
|
|
t.Fatalf("ParseShareSet() = %+v, %q, %v", got, role, err)
|
|
}
|
|
}
|
|
|
|
listID, role, err := ParseShareRole(ShareRoleData(42, domain.RoleEditor))
|
|
if err != nil || listID != 42 || role != domain.RoleEditor {
|
|
t.Fatalf("ParseShareRole() = %d, %q, %v", listID, role, err)
|
|
}
|
|
}
|
|
|
|
func TestShareCallbackRejectsBadData(t *testing.T) {
|
|
for _, data := range []string{
|
|
"v1:share_role:42",
|
|
"v1:share_role:0:editor",
|
|
"v1:share_role:42:owner",
|
|
"v1:share_view:42:u",
|
|
"v1:share_view:42:x:7",
|
|
"v1:share_view:42:u:0",
|
|
"v1:share_set:42:u:7",
|
|
"v1:share_set:42:u:7:owner",
|
|
"v1:share_revoke:42:u",
|
|
"share_view:42:u:7",
|
|
} {
|
|
if !rejectsShareData(data) {
|
|
t.Fatalf("accepted invalid callback data %q", data)
|
|
}
|
|
}
|
|
}
|
|
|
|
func rejectsShareData(data string) bool {
|
|
if _, _, err := ParseShareSet(data); err == nil {
|
|
return false
|
|
}
|
|
if _, err := ParseShareRef(data, ActionShareView); err == nil {
|
|
return false
|
|
}
|
|
if _, err := ParseShareRef(data, ActionShareRevoke); err == nil {
|
|
return false
|
|
}
|
|
if _, _, err := ParseShareRole(data); err == nil {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func TestCallbackBuildersFitTelegramLimit(t *testing.T) {
|
|
ref := ShareRef{ListID: 9223372036854775807, ShareID: 9223372036854775807}
|
|
data := []string{
|
|
NavLists, NavNew, NavHelp,
|
|
ListData(1 << 62),
|
|
RenameListData(1 << 62),
|
|
DeleteListData(1 << 62),
|
|
DeleteListYesData(1 << 62),
|
|
SharesData(1 << 62),
|
|
PageData(1<<62, 1<<30),
|
|
ShareAddData(1 << 62),
|
|
ShareRoleData(1<<62, domain.RoleEditor),
|
|
ShareViewData(ref),
|
|
ShareSetData(ref, domain.RoleEditor),
|
|
ShareRevokeData(ref),
|
|
ShareRevokeYesData(ref),
|
|
}
|
|
for _, item := range data {
|
|
if len(item) > MaxCallbackDataLength {
|
|
t.Fatalf("callback data %q is %d bytes, limit %d",
|
|
item, len(item), MaxCallbackDataLength)
|
|
}
|
|
}
|
|
}
|