From 86a83a24caff617a47b298784ba8a5b26119585d Mon Sep 17 00:00:00 2001 From: Dima Krasner Date: Wed, 27 Sep 2023 08:49:58 +0300 Subject: [PATCH] add even more tests again --- front/search.go | 2 +- test/federated_test.go | 70 ++++++++++++++++++++ test/follows_test.go | 83 +++++++++++++++++++++++ test/home_test.go | 38 +++++++++++ test/inbox_test.go | 145 +++++++++++++++++++++++++++++++++++++++++ test/search_test.go | 78 ++++++++++++++++++++++ 6 files changed, 415 insertions(+), 1 deletion(-) create mode 100644 test/federated_test.go create mode 100644 test/follows_test.go create mode 100644 test/home_test.go create mode 100644 test/search_test.go diff --git a/front/search.go b/front/search.go index bb37aa20..52858ac9 100644 --- a/front/search.go +++ b/front/search.go @@ -29,7 +29,7 @@ func search(w text.Writer, r *request) { hashtag, err := url.QueryUnescape(r.URL.RawQuery) if err != nil { - r.Log.Info("Failed to decode user name", "url", r.URL, "error", err) + r.Log.Info("Failed to decode query", "url", r.URL, "error", err) w.Status(40, "Bad input") return } diff --git a/test/federated_test.go b/test/federated_test.go new file mode 100644 index 00000000..b379b680 --- /dev/null +++ b/test/federated_test.go @@ -0,0 +1,70 @@ +/* +Copyright 2023 Dima Krasner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package test + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestFederated_AuthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + federated := server.Handle("/users/federated", server.Alice) + assert.Regexp(t, "^20 text/gemini\r\n", federated) +} + +func TestFederated_UnauthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + federated := server.Handle("/federated", nil) + assert.Regexp(t, "^20 text/gemini\r\n", federated) +} + +func TestFederated_InvalidOffset(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + federated := server.Handle("/users/federated?a", server.Alice) + assert.Equal(t, "40 Invalid query\r\n", federated) +} + +func TestFederated_BigOffset(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + federated := server.Handle("/users/federated?901", server.Alice) + assert.Equal(t, "40 Offset must be <= 900\r\n", federated) +} + +func TestFederated_SecondPage(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + federated := server.Handle("/users/federated?30", server.Alice) + assert.Regexp(t, "^20 text/gemini\r\n", federated) +} + +func TestFederated_SecondPageUnauthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + federated := server.Handle("/federated?30", nil) + assert.Regexp(t, "^20 text/gemini\r\n", federated) +} diff --git a/test/follows_test.go b/test/follows_test.go new file mode 100644 index 00000000..326d1f65 --- /dev/null +++ b/test/follows_test.go @@ -0,0 +1,83 @@ +/* +Copyright 2023 Dima Krasner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package test + +import ( + "crypto/sha256" + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestFollows_NoFollows(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follows := server.Handle("/users/follows", server.Alice) + assert.Contains(t, follows, "No followed users.") +} + +func TestFollows_TwoInactive(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follows := server.Handle("/users/follows", server.Alice) + assert.Contains(t, follows, server.Bob.PreferredUsername) + assert.NotContains(t, follows, server.Carol.PreferredUsername) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + follows = server.Handle("/users/follows", server.Alice) + assert.Contains(t, follows, server.Bob.PreferredUsername) + assert.Contains(t, follows, server.Carol.PreferredUsername) +} + +func TestFollows_OneActiveOneInactive(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + follows := server.Handle("/users/follows", server.Alice) + assert.Contains(t, follows, server.Bob.PreferredUsername) + assert.NotContains(t, follows, "1 post") + assert.Contains(t, follows, server.Carol.PreferredUsername) + + whisper := server.Handle("/users/whisper?Hello%20world", server.Bob) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + follows = server.Handle("/users/follows", server.Alice) + assert.Contains(t, follows, server.Bob.PreferredUsername) + assert.Contains(t, follows, "1 post") + assert.Contains(t, follows, server.Carol.PreferredUsername) +} + +func TestFollows_UnauthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follows := server.Handle("/users/follows", nil) + assert.Equal(t, "30 /users\r\n", follows) +} diff --git a/test/home_test.go b/test/home_test.go new file mode 100644 index 00000000..ed404eda --- /dev/null +++ b/test/home_test.go @@ -0,0 +1,38 @@ +/* +Copyright 2023 Dima Krasner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package test + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestHome_AuthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + home := server.Handle("/", server.Alice) + assert.Equal(t, "30 /users\r\n", home) +} + +func TestHome_UnauthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + home := server.Handle("/", nil) + assert.Regexp(t, "^20 text/gemini\r\n", home) +} diff --git a/test/inbox_test.go b/test/inbox_test.go index 229dad9a..070feea9 100644 --- a/test/inbox_test.go +++ b/test/inbox_test.go @@ -20,6 +20,7 @@ import ( "crypto/sha256" "fmt" "github.com/stretchr/testify/assert" + "strings" "testing" "time" ) @@ -119,3 +120,147 @@ func TestInbox_PostToFollowersYesterday(t *testing.T) { yesterday := server.Handle("/users/inbox/yesterday", server.Alice) assert.Contains(t, yesterday, "No posts.") } + +func TestInbox_MentionAndNoMention(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + whisper := server.Handle("/users/whisper?Hello%20%40alice%21", server.Bob) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + whisper = server.Handle("/users/whisper?Hello%20alice%21", server.Carol) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + today := server.Handle("/users/inbox/today", server.Alice) + postWithMention := strings.Index(today, "Hello @alice!") + postWithoutMention := strings.Index(today, "Hello alice!") + assert.NotEqual(t, postWithMention, -1) + assert.NotEqual(t, postWithoutMention, -1) + assert.True(t, postWithMention < postWithoutMention) +} + +func TestInbox_LeadingMentionAndNoMention(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + whisper := server.Handle("/users/whisper?%40alice%20Hello", server.Bob) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + whisper = server.Handle("/users/whisper?Hello%20alice%21", server.Carol) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + today := server.Handle("/users/inbox/today", server.Alice) + postWithMention := strings.Index(today, "@alice Hello") + postWithoutMention := strings.Index(today, "Hello alice!") + assert.NotEqual(t, postWithMention, -1) + assert.NotEqual(t, postWithoutMention, -1) + assert.True(t, postWithMention < postWithoutMention) +} + +func TestInbox_LeadingMentionAndCommaAndNoMention(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + whisper := server.Handle("/users/whisper?%40alice%2c%20Hello", server.Bob) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + whisper = server.Handle("/users/whisper?Hello%20alice%21", server.Carol) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + today := server.Handle("/users/inbox/today", server.Alice) + postWithMention := strings.Index(today, "@alice, Hello") + postWithoutMention := strings.Index(today, "Hello alice!") + assert.NotEqual(t, postWithMention, -1) + assert.NotEqual(t, postWithoutMention, -1) + assert.True(t, postWithMention < postWithoutMention) +} + +func TestInbox_NoMentionAndMention(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + whisper := server.Handle("/users/whisper?Hello%20alice%21", server.Bob) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + whisper = server.Handle("/users/whisper?Hello%20%40alice%21", server.Carol) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + today := server.Handle("/users/inbox/today", server.Alice) + postWithMention := strings.Index(today, "Hello @alice!") + postWithoutMention := strings.Index(today, "Hello alice!") + assert.NotEqual(t, postWithMention, -1) + assert.NotEqual(t, postWithoutMention, -1) + assert.True(t, postWithMention < postWithoutMention) +} + +func TestInbox_DMWithoutMentionAndMention(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + dm := server.Handle(fmt.Sprintf("/users/dm/%x?Hello%%20Alice", sha256.Sum256([]byte(server.Alice.ID))), server.Bob) + assert.Regexp(t, "^30 /users/view/[0-9a-f]{64}\r\n$", dm) + + whisper := server.Handle("/users/whisper?Hello%20%40alice%21", server.Carol) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + today := server.Handle("/users/inbox/today", server.Alice) + dmWithoutMention := strings.Index(today, "Hello Alice") + postWithMention := strings.Index(today, "Hello @alice!") + assert.NotEqual(t, dmWithoutMention, -1) + assert.NotEqual(t, postWithMention, -1) + assert.True(t, dmWithoutMention < postWithMention) +} + +func TestInbox_MentionAndDMWithoutMention(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + follow := server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Bob.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Bob.ID))), follow) + + follow = server.Handle(fmt.Sprintf("/users/follow/%x", sha256.Sum256([]byte(server.Carol.ID))), server.Alice) + assert.Equal(t, fmt.Sprintf("30 /users/outbox/%x\r\n", sha256.Sum256([]byte(server.Carol.ID))), follow) + + whisper := server.Handle("/users/whisper?Hello%20%40alice%21", server.Bob) + assert.Regexp(t, "30 /users/view/[0-9a-f]{64}", whisper) + + dm := server.Handle(fmt.Sprintf("/users/dm/%x?Hello%%20Alice", sha256.Sum256([]byte(server.Alice.ID))), server.Carol) + assert.Regexp(t, "^30 /users/view/[0-9a-f]{64}\r\n$", dm) + + today := server.Handle("/users/inbox/today", server.Alice) + dmWithoutMention := strings.Index(today, "Hello Alice") + postWithMention := strings.Index(today, "Hello @alice!") + assert.NotEqual(t, dmWithoutMention, -1) + assert.NotEqual(t, postWithMention, -1) + assert.True(t, dmWithoutMention < postWithMention) +} diff --git a/test/search_test.go b/test/search_test.go new file mode 100644 index 00000000..73ea3182 --- /dev/null +++ b/test/search_test.go @@ -0,0 +1,78 @@ +/* +Copyright 2023 Dima Krasner + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package test + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestSearch_Happyflow(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/users/search?world", server.Bob) + assert.Equal(t, "30 /users/hashtag/world\r\n", search) +} + +func TestSearch_LeadingHash(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/users/search?%23world", server.Bob) + assert.Equal(t, "30 /users/hashtag/world\r\n", search) +} + +func TestSearch_LeadingHashUnauthenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/search?%23world", nil) + assert.Equal(t, "30 /hashtag/world\r\n", search) +} + +func TestSearch_NoInput(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/users/search?", server.Bob) + assert.Equal(t, "10 Hashtag\r\n", search) +} + +func TestSearch_EmptyInput(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/users/search?", server.Bob) + assert.Equal(t, "10 Hashtag\r\n", search) +} + +func TestSearch_InvalidEscapeSequence(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/users/search?%zzworld", server.Bob) + assert.Equal(t, "40 Bad input\r\n", search) +} + +func TestSearch_UnathenticatedUser(t *testing.T) { + server := newTestServer() + defer server.Shutdown() + + search := server.Handle("/search?world", nil) + assert.Equal(t, "30 /hashtag/world\r\n", search) +}