From a7f9bebe6a8070442413c4ec24adaf40cbcd14d7 Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 27 Oct 2026 08:28:28 +0100 Subject: [PATCH] Run the internal/handlers tests in parallel (closes #194) The handlers tests ran one at a time because config.New writes the global viper instance. Each test spends most of its time in SQLite under the race detector, so run in a row they took longer than the 20-second target. Every test and subtest now calls t.Parallel(), as the ircserver and db tests already do. A mutex in newTestServerWith makes tests start their servers one at a time, since config.New writes viper and the server reads it as it starts. No test is removed or otherwise changed. Model: opus-5-5 Co-authored-by: clawbot --- internal/handlers/api_test.go | 278 +++++++++++++++++++++++++++++- internal/handlers/utility_test.go | 11 +- 2 files changed, 284 insertions(+), 5 deletions(-) diff --git a/internal/handlers/api_test.go b/internal/handlers/api_test.go index 6ca6421..9201f1c 100644 --- a/internal/handlers/api_test.go +++ b/internal/handlers/api_test.go @@ -1,7 +1,3 @@ -// Tests use a global viper instance for configuration, -// making parallel execution unsafe. -// -//nolint:paralleltest package handlers_test import ( @@ -143,6 +139,13 @@ type testServer struct { handlers *handlers.Handlers } +// viperMu makes tests start their servers one at a time, +// because config.New writes the global viper instance and +// the server reads it as it starts. +// +//nolint:gochecknoglobals // guards a global, so must be one +var viperMu sync.Mutex + func newTestServer( t *testing.T, ) *testServer { @@ -158,6 +161,9 @@ func newTestServerWith( ) *testServer { t.Helper() + viperMu.Lock() + defer viperMu.Unlock() + // A random name, so that no other test can share it, not // even one that has finished but still holds its database // open. @@ -625,6 +631,8 @@ func findNumeric( // --- Tests --- func TestCreateSessionValid(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) cookie := tserver.createSession("alice") @@ -634,6 +642,8 @@ func TestCreateSessionValid(t *testing.T) { } func TestWelcomeNumeric(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("welcomer") @@ -648,6 +658,8 @@ func TestWelcomeNumeric(t *testing.T) { } func TestJoinNumerics(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("jnumtest") @@ -675,6 +687,8 @@ func TestJoinNumerics(t *testing.T) { } func TestCreateSessionDuplicate(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) tserver.createSession("alice") @@ -694,6 +708,8 @@ func TestCreateSessionDuplicate(t *testing.T) { // second test server leaves the first one's database alone and // starts on an empty one of its own. func TestEachTestServerHasItsOwnDatabase(t *testing.T) { + t.Parallel() + first := newTestServer(t) first.createSession("samenick") @@ -714,6 +730,8 @@ func TestEachTestServerHasItsOwnDatabase(t *testing.T) { } func TestCreateSessionEmpty(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp := postSession(t, tserver, "") @@ -728,6 +746,8 @@ func TestCreateSessionEmpty(t *testing.T) { } func TestCreateSessionInvalidChars(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp := postSession(t, tserver, "hello world") @@ -742,6 +762,8 @@ func TestCreateSessionInvalidChars(t *testing.T) { } func TestCreateSessionNumericStart(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp := postSession(t, tserver, "123abc") @@ -756,6 +778,8 @@ func TestCreateSessionNumericStart(t *testing.T) { } func TestCreateSessionMalformed(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp, err := doRequest( @@ -778,6 +802,8 @@ func TestCreateSessionMalformed(t *testing.T) { } func TestAuthNoCookie(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) status, _ := tserver.getState("") @@ -787,6 +813,8 @@ func TestAuthNoCookie(t *testing.T) { } func TestAuthBadCookie(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) status, _ := tserver.getState( @@ -798,6 +826,8 @@ func TestAuthBadCookie(t *testing.T) { } func TestAuthValidToken(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("authtest") @@ -815,6 +845,8 @@ func TestAuthValidToken(t *testing.T) { } func TestJoinChannel(t *testing.T) { + t.Parallel() + const channel = "#test" tserver := newTestServer(t) @@ -840,6 +872,8 @@ func TestJoinChannel(t *testing.T) { } func TestJoinWithoutHash(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("joiner2") @@ -864,6 +898,8 @@ func TestJoinWithoutHash(t *testing.T) { } func TestPartChannel(t *testing.T) { + t.Parallel() + const channel = "#test" tserver := newTestServer(t) @@ -896,6 +932,8 @@ func TestPartChannel(t *testing.T) { } func TestJoinMissingTo(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("joiner3") @@ -920,6 +958,8 @@ func TestJoinMissingTo(t *testing.T) { } func TestChannelMessage(t *testing.T) { + t.Parallel() + const channel = "#test" tserver := newTestServer(t) @@ -966,6 +1006,8 @@ func TestChannelMessage(t *testing.T) { } func TestMessageMissingBody(t *testing.T) { + t.Parallel() + const channel = "#test" tserver := newTestServer(t) @@ -995,6 +1037,8 @@ func TestMessageMissingBody(t *testing.T) { } func TestMessageMissingTo(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("noto") @@ -1019,6 +1063,8 @@ func TestMessageMissingTo(t *testing.T) { } func TestNonMemberCannotSend(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) aliceToken := tserver.createSession("alice_nosend") bobToken := tserver.createSession("bob_nosend") @@ -1054,6 +1100,8 @@ func TestNonMemberCannotSend(t *testing.T) { } func TestDirectMessage(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) aliceToken := tserver.createSession("alice_dm") bobToken := tserver.createSession("bob_dm") @@ -1095,6 +1143,8 @@ func TestDirectMessage(t *testing.T) { } func TestDMToNonexistentUser(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("dmsender") @@ -1120,6 +1170,8 @@ func TestDMToNonexistentUser(t *testing.T) { } func TestNickChange(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("nick_test") @@ -1144,6 +1196,8 @@ func TestNickChange(t *testing.T) { } func TestNickSameAsCurrent(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("same_nick") @@ -1157,6 +1211,8 @@ func TestNickSameAsCurrent(t *testing.T) { } func TestNickCollision(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("nickuser") @@ -1183,6 +1239,8 @@ func TestNickCollision(t *testing.T) { } func TestNickInvalid(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("nickval") @@ -1207,6 +1265,8 @@ func TestNickInvalid(t *testing.T) { } func TestNickEmptyBody(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("nicknobody") @@ -1230,6 +1290,8 @@ func TestNickEmptyBody(t *testing.T) { } func TestTopic(t *testing.T) { + t.Parallel() + const channel = "#topictest" tserver := newTestServer(t) @@ -1261,6 +1323,8 @@ func TestTopic(t *testing.T) { } func TestTopicMissingTo(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("topicnoto") @@ -1285,6 +1349,8 @@ func TestTopicMissingTo(t *testing.T) { } func TestTopicMissingBody(t *testing.T) { + t.Parallel() + const channel = "#topictest" tserver := newTestServer(t) @@ -1314,6 +1380,8 @@ func TestTopicMissingBody(t *testing.T) { } func TestTopicNonMember(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) aliceToken := tserver.createSession("alice_topic") bobToken := tserver.createSession("bob_topic") @@ -1350,6 +1418,8 @@ func TestTopicNonMember(t *testing.T) { } func TestPing(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("ping_user") @@ -1369,6 +1439,8 @@ func TestPing(t *testing.T) { } func TestQuit(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("quitter") observerToken := tserver.createSession("observer") @@ -1417,6 +1489,8 @@ const quitRaceTrials = 5 // clients of a session log out at once, the session's QUIT // is sent once. func TestConcurrentLogoutsSendOneQuit(t *testing.T) { + t.Parallel() + checkQuitRace(t, func(tserver *testServer, tokens []string) { tserver.postConcurrently(apiLogout, nil, tokens...) }) @@ -1426,6 +1500,8 @@ func TestConcurrentLogoutsSendOneQuit(t *testing.T) { // clients of a session send QUIT at once, the session's // QUIT is sent once. func TestConcurrentQuitsSendOneQuit(t *testing.T) { + t.Parallel() + quit, err := json.Marshal(map[string]any{commandKey: irc.CmdQuit}) if err != nil { t.Fatal(err) @@ -1498,6 +1574,8 @@ func checkQuitRace( // its channel peer gets no QUIT, and that the other // client's logout then sends one QUIT. func TestLogoutOfOneClientKeepsSession(t *testing.T) { + t.Parallel() + const ( nick = "twoclients" channel = "#logouts" @@ -1560,6 +1638,8 @@ func TestLogoutOfOneClientKeepsSession(t *testing.T) { // nothing: the client's token still works, the session is // still on its channel and its channel peer has no QUIT. func TestFailedLogoutChangesNothing(t *testing.T) { + t.Parallel() + const ( nick = "stuckleaver" channel = "#stuck" @@ -1637,6 +1717,8 @@ const ( // wakes the long poll of a user who shares a channel with // it. func TestQuitWakesPeerLongPoll(t *testing.T) { + t.Parallel() + const reason = "gone fishing" checkQuitWakesPoll(t, reason, func(tserver *testServer, token string) { @@ -1650,6 +1732,8 @@ func TestQuitWakesPeerLongPoll(t *testing.T) { // a session's last client wakes the long poll of a user who // shares a channel with it. func TestLastLogoutWakesPeerLongPoll(t *testing.T) { + t.Parallel() + checkQuitWakesPoll(t, "Connection closed", func(tserver *testServer, token string) { tserver.logout(token) }) @@ -1890,6 +1974,8 @@ func (tserver *testServer) postConcurrently( } func TestUnknownCommand(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("cmdtest") @@ -1913,6 +1999,8 @@ func TestUnknownCommand(t *testing.T) { } func TestEmptyCommand(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("emptycmd") @@ -1925,6 +2013,8 @@ func TestEmptyCommand(t *testing.T) { } func TestHistory(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("historian") @@ -1972,6 +2062,8 @@ func TestHistory(t *testing.T) { } func TestHistoryNonMember(t *testing.T) { + t.Parallel() + const channel = "#secret" tserver := newTestServer(t) @@ -2102,6 +2194,8 @@ func (tserver *testServer) getAllHistory( } func TestHistoryPaging(t *testing.T) { + t.Parallel() + const ( channel = "#paging" msgCount = 5 @@ -2149,6 +2243,8 @@ func TestHistoryPaging(t *testing.T) { // and none sent to another session, and checks that the id // of a DM sent to another session is not accepted as before. func TestHistoryDMPaging(t *testing.T) { + t.Parallel() + const ( firstNick = "readerFirst" laterNick = "readerLater" @@ -2220,6 +2316,8 @@ func TestHistoryDMPaging(t *testing.T) { } func TestHistoryUnknownBefore(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("lost") @@ -2280,6 +2378,8 @@ func TestHistoryUnknownBefore(t *testing.T) { // released by QUIT does not get the DMs sent to its previous // holder. func TestHistoryReusedNick(t *testing.T) { + t.Parallel() + const victim = "victimV" tserver := newTestServer(t) @@ -2324,6 +2424,8 @@ func TestHistoryReusedNick(t *testing.T) { // again under the name of a deleted one starts with no // history, even when the old one had a key. func TestHistoryRecreatedChannel(t *testing.T) { + t.Parallel() + const channel = "#priv" tserver := newTestServer(t) @@ -2372,6 +2474,8 @@ func TestHistoryRecreatedChannel(t *testing.T) { } func TestChannelList(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("lister") @@ -2421,6 +2525,8 @@ func TestChannelList(t *testing.T) { } func TestChannelMembers(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("membertest") @@ -2451,6 +2557,8 @@ func TestChannelMembers(t *testing.T) { } func TestLongPoll(t *testing.T) { + t.Parallel() + const channel = "#longpoll" tserver := newTestServer(t) @@ -2518,6 +2626,8 @@ func TestLongPoll(t *testing.T) { } func TestLongPollTimeout(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("lp_timeout") @@ -2563,6 +2673,8 @@ func TestLongPollTimeout(t *testing.T) { // poll waits, is returned at once and not when the poll times // out, and that the poll then holds no broker wait channel. func TestLongPollReturnsMessageQueuedAfterFirstRead(t *testing.T) { + t.Parallel() + const ( nick = "lp_late" sender = "lp_late_sender" @@ -2646,6 +2758,8 @@ var errReadFailed = errors.New("read failed") // whether it is answered at once, after its timeout, or with // an error because a read of the queue failed. func TestGetMessagesRemovesWaitChannel(t *testing.T) { + t.Parallel() + const ( // longTimeout, in seconds, is the timeout of the // requests that must be answered without waiting. @@ -2692,6 +2806,8 @@ func TestGetMessagesRemovesWaitChannel(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { + t.Parallel() + const nick = "wc_poller" tserver := newTestServer(t) @@ -2782,6 +2898,8 @@ func (tserver *testServer) getMessagesFailingRead( // a long poll whose client gives up while it waits leaves no // broker wait channel behind. func TestLongPollRemovesWaitChannelWhenClientGivesUp(t *testing.T) { + t.Parallel() + const ( nick = "wc_leaver" @@ -2916,6 +3034,8 @@ func (tserver *testServer) queueMessage( } func TestEphemeralChannelCleanup(t *testing.T) { + t.Parallel() + const channel = "#ephemeral" tserver := newTestServer(t) @@ -2960,6 +3080,8 @@ func TestEphemeralChannelCleanup(t *testing.T) { } func TestConcurrentSessions(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) var waitGroup sync.WaitGroup @@ -3021,6 +3143,8 @@ func TestConcurrentSessions(t *testing.T) { } func TestServerInfo(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp, err := doRequest( @@ -3043,6 +3167,8 @@ func TestServerInfo(t *testing.T) { } func TestHealthcheck(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp, err := doRequest( @@ -3079,6 +3205,8 @@ func TestHealthcheck(t *testing.T) { } func TestHealthcheckRuntimeStatsFields(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) resp, err := doRequest( @@ -3122,6 +3250,8 @@ func TestHealthcheckRuntimeStatsFields(t *testing.T) { } func TestHealthcheckRuntimeStatsValues(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("statsuser") @@ -3240,6 +3370,8 @@ func postJSONExpectStatus( } func TestPassCommand(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("passuser") @@ -3279,6 +3411,8 @@ const ( // counts bytes: "é" is two bytes in UTF-8, so 72 of them are // refused. func TestPassCommandLength(t *testing.T) { + t.Parallel() + cases := []struct { name string password string @@ -3294,6 +3428,8 @@ func TestPassCommandLength(t *testing.T) { for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("pwlength") @@ -3338,6 +3474,8 @@ func TestPassCommandLength(t *testing.T) { } func TestPassCommandEmpty(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("emptypw") @@ -3364,6 +3502,8 @@ func TestPassCommandEmpty(t *testing.T) { } func TestLoginValid(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // Create session and set password via PASS command. @@ -3432,6 +3572,8 @@ func TestLoginValid(t *testing.T) { } func TestLoginWrongPassword(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // Create session and set password via PASS command. @@ -3453,6 +3595,8 @@ func TestLoginWrongPassword(t *testing.T) { } func TestLoginNonexistentUser(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) postJSONExpectStatus( @@ -3466,6 +3610,8 @@ func TestLoginNonexistentUser(t *testing.T) { } func TestSessionCookie(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) body, err := json.Marshal( @@ -3532,6 +3678,8 @@ func TestSessionCookie(t *testing.T) { } func TestSessionStillWorks(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // Verify anonymous session creation still works. @@ -3599,6 +3747,8 @@ func getNumericParams( } func TestWhoisShowsHostInfo(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSessionWithUsername( @@ -3694,6 +3844,8 @@ func (tserver *testServer) createSessionWithUsername( } func TestWhoShowsHostInfo(t *testing.T) { + t.Parallel() + const channel = "#whotest" tserver := newTestServer(t) @@ -3759,6 +3911,8 @@ func assertWhoReplyUsername( } func TestSessionUsernameDefault(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // Create session without specifying username. @@ -3805,6 +3959,8 @@ func TestSessionUsernameDefault(t *testing.T) { } func TestLoginRateLimitExceeded(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // Exhaust the burst (default: 5 per IP) using @@ -3868,6 +4024,8 @@ func TestLoginRateLimitExceeded(t *testing.T) { } func TestLoginRateLimitAllowsNormalUse(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // Create session and set password via PASS command. @@ -3908,6 +4066,8 @@ func TestLoginRateLimitAllowsNormalUse(t *testing.T) { } func TestNickBroadcastToChannels(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) aliceToken := tserver.createSession("nick_a") bobToken := tserver.createSession("nick_b") @@ -3957,6 +4117,8 @@ func mintTestChannelHashcash( } func TestChannelHashcashSetMode(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("hcmode_user") @@ -3991,6 +4153,8 @@ func TestChannelHashcashSetMode(t *testing.T) { } func TestChannelHashcashQueryMode(t *testing.T) { + t.Parallel() + const channel = "#hcquery" tserver := newTestServer(t) @@ -4035,6 +4199,8 @@ func TestChannelHashcashQueryMode(t *testing.T) { } func TestChannelHashcashClearMode(t *testing.T) { + t.Parallel() + const channel = "#hcclear" tserver := newTestServer(t) @@ -4078,6 +4244,8 @@ func TestChannelHashcashClearMode(t *testing.T) { } func TestChannelHashcashRejectNoStamp(t *testing.T) { + t.Parallel() + const channel = "#hcreject" tserver := newTestServer(t) @@ -4121,6 +4289,8 @@ func TestChannelHashcashRejectNoStamp(t *testing.T) { } func TestChannelHashcashAcceptValidStamp(t *testing.T) { + t.Parallel() + const ( channel = "#hcaccept" text = "hello world" @@ -4186,6 +4356,8 @@ func TestChannelHashcashAcceptValidStamp(t *testing.T) { } func TestChannelHashcashRejectReplayedStamp(t *testing.T) { + t.Parallel() + const ( channel = "#hcreplay" text = "unique msg" @@ -4320,6 +4492,8 @@ func (tserver *testServer) sendConcurrently( // in several requests at once and checks that exactly one is // accepted and the other member receives exactly one copy. func TestChannelHashcashRejectConcurrentReplay(t *testing.T) { + t.Parallel() + const ( channel = "#hcrace" text = "one stamp" @@ -4395,6 +4569,8 @@ func TestChannelHashcashRejectConcurrentReplay(t *testing.T) { } func TestChannelHashcashNoRequirementWorks(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("hcnone_user") @@ -4423,6 +4599,8 @@ func TestChannelHashcashNoRequirementWorks(t *testing.T) { } func TestChannelHashcashInvalidBitsRange(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("hcbits_user") @@ -4450,6 +4628,8 @@ func TestChannelHashcashInvalidBitsRange(t *testing.T) { } func TestChannelHashcashMissingBitsArg(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("hcnoarg_user") @@ -4528,6 +4708,8 @@ func sessionCount(t *testing.T, tserver *testServer) int64 { // for its nick, and that no refused request creates a // session. func TestRefusedSessionLeavesStampUnspent(t *testing.T) { + t.Parallel() + const ( bits = 2 badNick = "bad nick" @@ -4592,6 +4774,8 @@ func TestRefusedSessionLeavesStampUnspent(t *testing.T) { } func TestNamesShowsHostmask(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) queryToken, lastID := setupChannelWithIdentMember( @@ -4613,6 +4797,8 @@ func TestNamesShowsHostmask(t *testing.T) { } func TestNamesOnJoinShowsHostmask(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) // First user joins to populate the channel. @@ -4739,6 +4925,8 @@ func newTestServerWithOper( } func TestOperCommandSuccess(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) token := tserver.createSession("operuser") @@ -4762,6 +4950,8 @@ func TestOperCommandSuccess(t *testing.T) { } func TestOperCommandFailure(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) token := tserver.createSession("badoper") @@ -4785,6 +4975,8 @@ func TestOperCommandFailure(t *testing.T) { } func TestOperCommandNeedMoreParams(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) token := tserver.createSession("shortoper") @@ -4808,6 +5000,8 @@ func TestOperCommandNeedMoreParams(t *testing.T) { } func TestOperWhoisShowsClientInfo(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) // Create a target user. @@ -4876,6 +5070,8 @@ func TestOperWhoisShowsClientInfo(t *testing.T) { } func TestNonOperWhoisHidesClientInfo(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) // Create a target user. @@ -4912,6 +5108,8 @@ func TestNonOperWhoisHidesClientInfo(t *testing.T) { } func TestWhoisShowsOperatorStatus(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) // Create oper user and authenticate. @@ -4951,6 +5149,8 @@ func TestWhoisShowsOperatorStatus(t *testing.T) { } func TestOperNoOlineConfigured(t *testing.T) { + t.Parallel() + // Standard test server has no oper configured. tserver := newTestServer(t) @@ -4981,6 +5181,8 @@ const kickCmd = "KICK" // TestOperatorAutoGrantOnCreate verifies that the first // user to join a channel (the creator) gets +o. func TestOperatorAutoGrantOnCreate(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("creator") @@ -5031,6 +5233,8 @@ func TestOperatorAutoGrantOnCreate(t *testing.T) { // TestSecondJoinerNotOperator verifies that subsequent // joiners do NOT get +o. func TestSecondJoinerNotOperator(t *testing.T) { + t.Parallel() + const channel = "#optest2" tserver := newTestServer(t) @@ -5085,6 +5289,8 @@ func TestSecondJoinerNotOperator(t *testing.T) { // TestModeGrantOperator tests MODE +o. func TestModeGrantOperator(t *testing.T) { + t.Parallel() + const channel = "#modeop" tserver := newTestServer(t) @@ -5148,6 +5354,8 @@ func TestModeGrantOperator(t *testing.T) { // TestModeRevokeOperator tests MODE -o. func TestModeRevokeOperator(t *testing.T) { + t.Parallel() + const channel = "#revoke" tserver := newTestServer(t) @@ -5202,6 +5410,8 @@ func TestModeRevokeOperator(t *testing.T) { // TestModeVoice tests MODE +v/-v. func TestModeVoice(t *testing.T) { + t.Parallel() + const channel = "#voice" tserver := newTestServer(t) @@ -5277,6 +5487,8 @@ func TestModeVoice(t *testing.T) { // TestModeNonOpCannotGrant verifies non-operators // cannot grant +o or +v. func TestModeNonOpCannotGrant(t *testing.T) { + t.Parallel() + const channel = "#noperm" tserver := newTestServer(t) @@ -5336,6 +5548,8 @@ func TestModeNonOpCannotGrant(t *testing.T) { // TestModeratedChannelBlocksNonVoiced tests +m mode. func TestModeratedChannelBlocksNonVoiced(t *testing.T) { + t.Parallel() + const channel = "#moderated" tserver := newTestServer(t) @@ -5379,6 +5593,8 @@ func TestModeratedChannelBlocksNonVoiced(t *testing.T) { // TestModeratedChannelAllowsOp tests that operators can // send in +m channels. func TestModeratedChannelAllowsOp(t *testing.T) { + t.Parallel() + const channel = "#modop" tserver := newTestServer(t) @@ -5426,6 +5642,8 @@ func TestModeratedChannelAllowsOp(t *testing.T) { // TestModeratedChannelAllowsVoiced tests that voiced // users can send in +m channels. func TestModeratedChannelAllowsVoiced(t *testing.T) { + t.Parallel() + const channel = "#modvoice" tserver := newTestServer(t) @@ -5479,6 +5697,8 @@ func TestModeratedChannelAllowsVoiced(t *testing.T) { // TestTopicLockDefaultOn verifies new channels have +t. func TestTopicLockDefaultOn(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("topiclock") @@ -5522,6 +5742,8 @@ func TestTopicLockDefaultOn(t *testing.T) { // TestTopicLockEnforced verifies non-operators cannot // change topic when +t is active. func TestTopicLockEnforced(t *testing.T) { + t.Parallel() + const channel = "#tlock" tserver := newTestServer(t) @@ -5558,6 +5780,8 @@ func TestTopicLockEnforced(t *testing.T) { // TestTopicLockOpCanChange verifies operators CAN change // topic when +t is active. func TestTopicLockOpCanChange(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) opToken := tserver.createSession("topicop2") @@ -5590,6 +5814,8 @@ func TestTopicLockOpCanChange(t *testing.T) { // TestTopicLockDisabled verifies that -t allows anyone // to change topic. func TestTopicLockDisabled(t *testing.T) { + t.Parallel() + const channel = "#tloff" tserver := newTestServer(t) @@ -5635,6 +5861,8 @@ func TestTopicLockDisabled(t *testing.T) { // TestKickByOperator tests that an operator can kick // a user. func TestKickByOperator(t *testing.T) { + t.Parallel() + const channel = "#kicktest" tserver := newTestServer(t) @@ -5692,6 +5920,8 @@ func TestKickByOperator(t *testing.T) { // TestKickByNonOperator tests that non-operators cannot // kick. func TestKickByNonOperator(t *testing.T) { + t.Parallel() + const channel = "#kickperm" tserver := newTestServer(t) @@ -5732,6 +5962,8 @@ func TestKickByNonOperator(t *testing.T) { // TestKickTargetNotInChannel tests kicking a user not // in the channel. func TestKickTargetNotInChannel(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) opToken := tserver.createSession("op_kicknot") _ = tserver.createSession("outsider") @@ -5762,6 +5994,8 @@ func TestKickTargetNotInChannel(t *testing.T) { // TestKickBroadcastToChannel verifies the KICK message // is broadcast to all channel members. func TestKickBroadcastToChannel(t *testing.T) { + t.Parallel() + const channel = "#kickbc" tserver := newTestServer(t) @@ -5799,6 +6033,8 @@ func TestKickBroadcastToChannel(t *testing.T) { // TestNoticeNoAwayReply verifies NOTICE doesn't trigger // RPL_AWAY. func TestNoticeNoAwayReply(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) senderToken := tserver.createSession("noticesend") awayToken := tserver.createSession("noticeaway") @@ -5832,6 +6068,8 @@ func TestNoticeNoAwayReply(t *testing.T) { // TestPrivmsgTriggersAway verifies PRIVMSG DOES trigger // RPL_AWAY. func TestPrivmsgTriggersAway(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) senderToken := tserver.createSession("msgsend") awayToken := tserver.createSession("msgaway") @@ -5865,6 +6103,8 @@ func TestPrivmsgTriggersAway(t *testing.T) { // TestNoticeSkipsHashcash verifies NOTICE bypasses // hashcash on +H channels. func TestNoticeSkipsHashcash(t *testing.T) { + t.Parallel() + const channel = "#hcnotice" tserver := newTestServer(t) @@ -5903,6 +6143,8 @@ func TestNoticeSkipsHashcash(t *testing.T) { // TestModeratedNoticeBlocked verifies +m blocks NOTICE // from non-voiced/non-op users too. func TestModeratedNoticeBlocked(t *testing.T) { + t.Parallel() + const channel = "#modnotice" tserver := newTestServer(t) @@ -5943,6 +6185,8 @@ func TestModeratedNoticeBlocked(t *testing.T) { // TestNonOpCannotSetModerated verifies non-operators // cannot set +m. func TestNonOpCannotSetModerated(t *testing.T) { + t.Parallel() + const channel = "#modperm" tserver := newTestServer(t) @@ -5975,6 +6219,8 @@ func TestNonOpCannotSetModerated(t *testing.T) { // TestISupportPrefix verifies PREFIX=(ov)@+ is in 005. func TestISupportPrefix(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("isupport") @@ -6002,6 +6248,8 @@ func TestISupportPrefix(t *testing.T) { // TestModeQueryShowsModerated verifies MODE query shows // +m when set. func TestModeQueryShowsModerated(t *testing.T) { + t.Parallel() + const channel = "#mqtest" tserver := newTestServer(t) @@ -6043,6 +6291,8 @@ func TestModeQueryShowsModerated(t *testing.T) { // TestKickDefaultReason verifies KICK uses kicker's // nick as default reason. func TestKickDefaultReason(t *testing.T) { + t.Parallel() + const channel = "#kickdef" tserver := newTestServer(t) @@ -6084,6 +6334,8 @@ const ( // TestBanAddRemoveList verifies +b add, list, and -b // remove via MODE commands. func TestBanAddRemoveList(t *testing.T) { + t.Parallel() + const channel = "#bans" tserver := newTestServer(t) @@ -6153,6 +6405,8 @@ func TestBanAddRemoveList(t *testing.T) { // TestBanBlocksJoin verifies that a banned user cannot // join a channel. func TestBanBlocksJoin(t *testing.T) { + t.Parallel() + const channel = "#banjoin" tserver := newTestServer(t) @@ -6186,6 +6440,8 @@ func TestBanBlocksJoin(t *testing.T) { // TestBanBlocksPrivmsg verifies that a banned user who // is already in a channel cannot send messages. func TestBanBlocksPrivmsg(t *testing.T) { + t.Parallel() + const channel = "#banmsg" tserver := newTestServer(t) @@ -6226,6 +6482,8 @@ func TestBanBlocksPrivmsg(t *testing.T) { // TestInviteOnlyJoin verifies +i behavior: join rejected // without invite, accepted with invite. func TestInviteOnlyJoin(t *testing.T) { + t.Parallel() + const channel = "#invonly" tserver := newTestServer(t) @@ -6279,6 +6537,8 @@ func TestInviteOnlyJoin(t *testing.T) { // TestSecretChannelHiddenFromList verifies +s hides a // channel from LIST for non-members. func TestSecretChannelHiddenFromList(t *testing.T) { + t.Parallel() + const channel = "#secret" tserver := newTestServer(t) @@ -6350,6 +6610,8 @@ func TestSecretChannelHiddenFromList(t *testing.T) { // TestChannelKeyJoin verifies +k behavior: wrong/missing // key is rejected, correct key allows join. func TestChannelKeyJoin(t *testing.T) { + t.Parallel() + const channel = "#keyed" tserver := newTestServer(t) @@ -6414,6 +6676,8 @@ func TestChannelKeyJoin(t *testing.T) { // TestUserLimitEnforcement verifies +l behavior: blocks // join when at capacity. func TestUserLimitEnforcement(t *testing.T) { + t.Parallel() + const channel = "#limited" tserver := newTestServer(t) @@ -6458,6 +6722,8 @@ func TestUserLimitEnforcement(t *testing.T) { // TestModeStringIncludesNewModes verifies that querying // channel mode returns the new modes (+i, +s, +k, +l). func TestModeStringIncludesNewModes(t *testing.T) { + t.Parallel() + const channel = "#modestr" tserver := newTestServer(t) @@ -6512,6 +6778,8 @@ func TestModeStringIncludesNewModes(t *testing.T) { // TestISUPPORT verifies the 005 numeric includes the // updated CHANMODES string. func TestISUPPORT(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("isupport") @@ -6538,6 +6806,8 @@ func TestISUPPORT(t *testing.T) { // TestNonOpCannotSetModes verifies non-operators // cannot set +i, +s, +k, +l, +b. func TestNonOpCannotSetModes(t *testing.T) { + t.Parallel() + const channel = "#noperm" tserver := newTestServer(t) diff --git a/internal/handlers/utility_test.go b/internal/handlers/utility_test.go index f5dea41..adcc9b8 100644 --- a/internal/handlers/utility_test.go +++ b/internal/handlers/utility_test.go @@ -1,4 +1,3 @@ -//nolint:paralleltest // global viper, as in api_test.go package handlers_test import ( @@ -72,6 +71,8 @@ func numericBody( } func TestUserhost(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("alice") @@ -109,6 +110,8 @@ func TestUserhost(t *testing.T) { } func TestVersionAdminInfoTime(t *testing.T) { + t.Parallel() + tserver := newTestServer(t) token := tserver.createSession("frank") @@ -147,6 +150,8 @@ func TestVersionAdminInfoTime(t *testing.T) { } func TestKill(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) victimToken := tserver.createSession("victim") @@ -213,6 +218,8 @@ func TestKill(t *testing.T) { } func TestWallops(t *testing.T) { + t.Parallel() + tserver := newTestServerWithOper(t) receiverToken := tserver.createSession("receiver") @@ -258,6 +265,8 @@ func TestWallops(t *testing.T) { } func TestUserMode(t *testing.T) { + t.Parallel() + const ( nick = "alice" other = "other"