From bc2b638b11f5b0a068e39ae51f7ac2782070d14f Mon Sep 17 00:00:00 2001 From: Eric Eastwood Date: Tue, 9 Jun 2026 10:45:36 -0500 Subject: [PATCH 1/7] Log `userID` when using `syncMembershipIn` to better differentiate checks (#879) Spawning from staring at some logs and wanting to know which user this pertains to without having to dive into the test source: ``` federation_rooms_invite_test.go:151: @user-58-alice:hs1 MustSyncUntil: timed out after 5.441786693s. Seen 6 /sync responses. Checkers: [t=391.995078ms] Response #1: syncMembershipIn(!nQhJEXkKJaajxcXaif:hs1, leave): check function did not pass while iterating ... ``` --- client/sync.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/sync.go b/client/sync.go index b3f71310..661abe33 100644 --- a/client/sync.go +++ b/client/sync.go @@ -347,7 +347,7 @@ func syncMembershipIn(userID, roomID, membership string, checks ...func(gjson.Re } else if membership == "knock" { roomTypeKey = "knock" } else { - return fmt.Errorf("syncMembershipIn(%s, %s): unknown membership: %s", roomID, membership, membership) + return fmt.Errorf("syncMembershipIn(%s, %s, %s): unknown membership: %s", userID, roomID, membership, membership) } } @@ -363,7 +363,7 @@ func syncMembershipIn(userID, roomID, membership string, checks ...func(gjson.Re } else if membership == "knock" { stateKey = "knock_state" } else { - return fmt.Errorf("syncMembershipIn(%s, %s): unknown membership: %s", roomID, membership, membership) + return fmt.Errorf("syncMembershipIn(%s, %s, %s): unknown membership: %s", userID, roomID, membership, membership) } } @@ -399,7 +399,7 @@ func syncMembershipIn(userID, roomID, membership string, checks ...func(gjson.Re } } - return fmt.Errorf("syncMembershipIn(%s, %s): %s & %s - %s", roomID, membership, firstErr, secondErr, topLevelSyncJSON) + return fmt.Errorf("syncMembershipIn(%s, %s, %s): %s & %s - %s", userID, roomID, membership, firstErr, secondErr, topLevelSyncJSON) } } From edfe298b6a9be6511c60920cf75397bb6731beb4 Mon Sep 17 00:00:00 2001 From: Erik Johnston Date: Tue, 16 Jun 2026 10:20:50 +0100 Subject: [PATCH 2/7] Fix race in `WithWaitForLeave` that flaked `TestPartialStateJoin/Outgoing_device_list_updates` (#878) --- ...federation_room_join_partial_state_test.go | 101 ++++++++++++++---- 1 file changed, 79 insertions(+), 22 deletions(-) diff --git a/tests/msc3902/federation_room_join_partial_state_test.go b/tests/msc3902/federation_room_join_partial_state_test.go index 9e11b163..622ff01b 100644 --- a/tests/msc3902/federation_room_join_partial_state_test.go +++ b/tests/msc3902/federation_room_join_partial_state_test.go @@ -123,10 +123,15 @@ func (s *server) AddEDUHandler(eduHandler func(gomatrixserverlib.EDU) bool) func } } -// WithWaitForLeave runs the given action and waits for the user to leave the room. +// WithWaitForLeave runs the given action and, when the resulting leave is +// expected to reach this server, waits for it. `leaveAction` is always run; the +// wait is skipped when `user` had already left the room (per their own +// homeserver, so the action produces no new leave) or when this server isn't in +// the room (so the leave won't be federated to us). func (s *server) WithWaitForLeave( - t *testing.T, room *federation.ServerRoom, userID string, leaveAction func(), + t *testing.T, room *federation.ServerRoom, user *client.CSAPI, leaveAction func(), ) { + userID := user.UserID leaveChannel := make(chan gomatrixserverlib.PDU, 10) removePDUHandler := s.AddPDUHandler( func(e gomatrixserverlib.PDU) bool { @@ -141,24 +146,76 @@ func (s *server) WithWaitForLeave( ) defer removePDUHandler() + // We need to check if the user (on their homeserver) thinks they're in the + // room, before performing the `leaveAction` (to avoid races). + // + // If they are not in the room, then the `leaveAction` will not produce a + // new leave event and we should not wait for one. + // + // If they are in the room then the `leaveAction` will produce a new leave + // event. We then need to check if we expect this server receive the leave + // event by checking if this server is in the room. If they are, we wait, if + // not we can return immediately after the `leaveAction`. + userInRoom := userIsJoinedTo(t, user, room.RoomID) + leaveAction() - memberEvent := room.CurrentState("m.room.member", userID) - membership := "" - if memberEvent != nil { - membership, _ = memberEvent.Membership() + if !userInRoom { + // The user had already left, so the action produced no new leave and + // none is coming: don't wait. + t.Logf("%s is not joined to test room %s; not waiting for them to leave.", userID, room.RoomID) + return } - if membership == "leave" { - t.Logf("%s has already seen %s leave test room %s.", s.ServerName(), userID, room.RoomID) - } else { - select { - case <-leaveChannel: - t.Logf("%s saw %s leave test room %s.", s.ServerName(), userID, room.RoomID) - break - case <-time.After(1 * time.Second): - t.Errorf("%s timed out waiting for %s to leave test room %s.", s.ServerName(), userID, room.RoomID) + + if !s.isInRoom(room) { + // The homeserver only federates the leave to servers that are in the + // room. If we aren't, no leave PDU is coming to us, so don't block until + // the timeout. + t.Logf("%s is not in test room %s; not waiting for %s to leave.", s.ServerName(), room.RoomID, userID) + return + } + + // Otherwise the action triggered the leave, which arrives as a PDU our + // handler matches. Wait on its channel rather than polling + // `room.CurrentState`: the room's current state is updated (by + // `room.AddEvent`) *before* the PDU callback runs, so returning on a + // `CurrentState` check could deregister our handler in the window before the + // callback fires, making the (expected) leave look unexpected to + // `HandleTransactionRequests`. This returns as soon as the leave arrives; the + // timeout is only a ceiling for declaring failure. + select { + case <-leaveChannel: + t.Logf("%s saw %s leave test room %s.", s.ServerName(), userID, room.RoomID) + case <-time.After(1 * time.Second): + t.Errorf("%s timed out waiting for %s to leave test room %s.", s.ServerName(), userID, room.RoomID) + } +} + +// isInRoom reports whether this Complement server has a joined user in the room, +// according to its own `ServerRoom` view. The server reliably tracks its own +// users' membership (it created their join/leave events), so this answers "will +// the homeserver federate events in this room to us?". +func (s *server) isInRoom(room *federation.ServerRoom) bool { + for _, serverInRoom := range room.ServersInRoom() { + if serverInRoom == s.ServerName() { + return true + } + } + return false +} + +// userIsJoinedTo reports whether the user is currently joined to the room, +// according to the user's own homeserver. +func userIsJoinedTo(t *testing.T, user *client.CSAPI, roomID string) bool { + t.Helper() + res := user.MustDo(t, "GET", []string{"_matrix", "client", "v3", "joined_rooms"}) + joinedRooms := gjson.ParseBytes(client.ParseJSON(t, res)).Get("joined_rooms") + for _, joinedRoom := range joinedRooms.Array() { + if joinedRoom.Str == roomID { + return true } } + return false } // Wait for the server to receive the event with given event ID. @@ -2249,7 +2306,7 @@ func TestPartialStateJoin(t *testing.T) { // @t23alice:hs1 joins the room. psjResult := beginPartialStateJoin(t, server1, room, alice) - defer server2.WithWaitForLeave(t, server2Room, alice.UserID, func() { psjResult.Destroy(t) }) + defer server2.WithWaitForLeave(t, server2Room, alice, func() { psjResult.Destroy(t) }) // Both homeservers should receive device list updates. renameDevice(t, alice, "A new device name 1") @@ -2296,7 +2353,7 @@ func TestPartialStateJoin(t *testing.T) { ) // NB: We register the `psjResult.Destroy()` cleanup twice. This is alright because it // is idempotent. Here we wait for server 2 to observe the leave too. - defer server2.WithWaitForLeave(t, server2Room, alice.UserID, func() { psjResult.Destroy(t) }) + defer server2.WithWaitForLeave(t, server2Room, alice, func() { psjResult.Destroy(t) }) joinEvent := room.CurrentState("m.room.member", server2.UserID("elsie")) server1.MustSendTransaction(t, deployment, deployment.GetFullyQualifiedHomeserverName(t, "hs1"), []json.RawMessage{joinEvent.JSON()}, nil) awaitEventViaSync(t, alice, room.RoomID, joinEvent.EventID(), "") @@ -2473,7 +2530,7 @@ func TestPartialStateJoin(t *testing.T) { syncToken = awaitEventViaSync(t, alice, partialStateRoom.RoomID, leaveEvent.EventID(), syncToken) leaveSharedRoom = func() { - server2.WithWaitForLeave(t, server2Room, alice.UserID, func() { + server2.WithWaitForLeave(t, server2Room, alice, func() { alice.MustLeaveRoom(t, roomID) }) } @@ -2533,7 +2590,7 @@ func TestPartialStateJoin(t *testing.T) { // @t26alice:hs1 joins the room, followed by @elsie:server2. // @elsie:server2 is kicked with an invalid event. syncToken, server2Room, psjResult := setupIncorrectlyAcceptedKick(t, deployment, alice, server1, server2, deviceListUpdateChannel1, deviceListUpdateChannel2, room) - defer server2.WithWaitForLeave(t, server2Room, alice.UserID, func() { psjResult.Destroy(t) }) + defer server2.WithWaitForLeave(t, server2Room, alice, func() { psjResult.Destroy(t) }) // @t26alice:hs1 sends out a device list update which is missed by @elsie:server2. // @elsie:server2 must receive missed device list updates once the partial state join finishes. @@ -2593,7 +2650,7 @@ func TestPartialStateJoin(t *testing.T) { federation.WithPartialState(), ) psjResult := beginPartialStateJoin(t, server1, room, alice) - defer server2.WithWaitForLeave(t, server2Room, alice.UserID, func() { psjResult.Destroy(t) }) + defer server2.WithWaitForLeave(t, server2Room, alice, func() { psjResult.Destroy(t) }) // @t28alice:hs1 sends out a device list update which is missed by @elsie:server2. // @elsie:server2 must receive missed device list updates once the partial state join finishes. @@ -2996,7 +3053,7 @@ func TestPartialStateJoin(t *testing.T) { }, client.SyncJoinedTo(server.UserID("charlie"), otherRoomID), ) - defer server.WithWaitForLeave(t, otherRoom, alice.UserID, func() { alice.MustLeaveRoom(t, otherRoomID) }) + defer server.WithWaitForLeave(t, otherRoom, alice, func() { alice.MustLeaveRoom(t, otherRoomID) }) // Depending on the homeserver implementation, @t31alice:hs1 must have been told that either: // * charlie updated their device list, or @@ -4422,7 +4479,7 @@ func (psj *partialStateJoinResult) Destroy(t *testing.T) { psj.Server.WithWaitForLeave( t, psj.ServerRoom, - psj.User.UserID, + psj.User, func() { psj.User.MustLeaveRoom(t, psj.ServerRoom.RoomID) }, ) } From 44d3bf5de0f6d3165e2e73890325a573a0d4cfd7 Mon Sep 17 00:00:00 2001 From: FrenchGithubUser Date: Thu, 18 Jun 2026 15:13:19 +0200 Subject: [PATCH 3/7] test: make sure that `allowed_room_ids` is included in the `/summary` client-server API response for rooms with restricted join rules, as required by Matrix 1.15. (#873) client-server API response for rooms with restricted join rules, as required by Matrix 1.15. --- tests/room_summary_test.go | 81 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 tests/room_summary_test.go diff --git a/tests/room_summary_test.go b/tests/room_summary_test.go new file mode 100644 index 00000000..31d87f47 --- /dev/null +++ b/tests/room_summary_test.go @@ -0,0 +1,81 @@ +// Tests the GET /_matrix/client/v1/room_summary/{roomIdOrAlias} endpoint +// as specified in https://spec.matrix.org/v1.15/client-server-api/#get_matrixclientv1room_summaryroomidoralias + +package tests + +import ( + "testing" + + "github.com/matrix-org/complement" + "github.com/matrix-org/complement/helpers" + "github.com/matrix-org/complement/match" + "github.com/matrix-org/complement/must" +) + +// TestRoomSummaryAllowedRoomIDs checks that the /summary endpoint includes +// allowed_room_ids for rooms with restricted join rules, and omits the field +// for rooms that do not use restricted join rules. +func TestRoomSummaryAllowedRoomIDs(t *testing.T) { + deployment := complement.Deploy(t, 1) + defer deployment.Destroy(t) + + alice := deployment.Register(t, "hs1", helpers.RegistrationOpts{}) + + // Create a space that will be referenced by the restricted room. + space := alice.MustCreateRoom(t, map[string]interface{}{ + "preset": "public_chat", + "creation_content": map[string]interface{}{ + "type": "m.space", + }, + }) + + // Create a room version 8 room with restricted join rules allowing members + // of the space above. + restrictedRoom := alice.MustCreateRoom(t, map[string]interface{}{ + "preset": "public_chat", + "room_version": "8", + "initial_state": []map[string]interface{}{ + { + "type": "m.room.join_rules", + "state_key": "", + "content": map[string]interface{}{ + "join_rule": "restricted", + "allow": []map[string]interface{}{ + { + "type": "m.room_membership", + "room_id": &space, + }, + }, + }, + }, + }, + }) + + // Create an invite-only room. + inviteRoom := alice.MustCreateRoom(t, map[string]interface{}{ + "preset": "private_chat", + }) + + t.Run("restricted room includes allowed_room_ids", func(t *testing.T) { + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "room_summary", restrictedRoom}) + must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 200, + JSON: []match.JSON{ + match.JSONKeyEqual("room_id", restrictedRoom), + match.JSONKeyEqual("join_rule", "restricted"), + match.JSONKeyEqual("allowed_room_ids", []interface{}{space}), + }, + }) + }) + + t.Run("non-restricted room omits allowed_room_ids", func(t *testing.T) { + res := alice.MustDo(t, "GET", []string{"_matrix", "client", "v1", "room_summary", inviteRoom}) + must.MatchResponse(t, res, match.HTTPResponse{ + StatusCode: 200, + JSON: []match.JSON{ + match.JSONKeyEqual("room_id", inviteRoom), + match.JSONKeyMissing("allowed_room_ids"), + }, + }) + }) +} From 6ac42a57843a5b2f569019fa13df6c2f06eef7af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Jun 2026 12:20:35 +0100 Subject: [PATCH 4/7] Bump actions/checkout from 6 to 6.0.2 in the minor-and-patches group across 1 directory (#877) --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5a017dac..528d0f21 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,7 @@ jobs: complement-internal: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 # Checkout complement + - uses: actions/checkout@v6.0.2 # Checkout complement - uses: actions/setup-go@v6 with: go-version-file: go.mod @@ -54,7 +54,7 @@ jobs: timeout: 10m steps: - - uses: actions/checkout@v6 # Checkout complement + - uses: actions/checkout@v6.0.2 # Checkout complement - uses: actions/setup-go@v6 with: From fd276dad888912b5ad58da9ec49d536a05421f8c Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Sat, 20 Jun 2026 19:31:09 +0100 Subject: [PATCH 5/7] Run the cleanup routines even if the main goroutine panics (#882) We should stop any running containers on panic, and things like complement-crypto expect their cleanup handlers to be run. --- test_main.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/test_main.go b/test_main.go index 39f87f5f..a208a6aa 100644 --- a/test_main.go +++ b/test_main.go @@ -76,12 +76,20 @@ func TestMain(m *testing.M, namespace string, customOpts ...opt) { fmt.Printf("Error: %s", err) os.Exit(1) } - exitCode := m.Run() - if opts.cleanup != nil { - opts.cleanup(testPackage.Config) + + // Run the cleanup functions even on panic. + // Note that deferred functions aren't run on `os.Exit`, so we need to put the `defer` calls + // inside a new `func()`. + runAndCleanup := func() int { + defer testPackage.Cleanup() + if opts.cleanup != nil { + defer opts.cleanup(testPackage.Config) + } + + return m.Run() } - testPackage.Cleanup() - os.Exit(exitCode) + + os.Exit(runAndCleanup()) } // Deploy will deploy the given blueprint or terminate the test. From c4dc3dde96d4e68149ceeaf63652c1c43544a9aa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 08:58:16 +0000 Subject: [PATCH 6/7] Bump actions/checkout from 6.0.2 to 6.0.3 in the minor-and-patches group (#883) Signed-off-by: dependabot[bot] --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 528d0f21..b328c5d1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,7 +14,7 @@ jobs: complement-internal: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6.0.2 # Checkout complement + - uses: actions/checkout@v6.0.3 # Checkout complement - uses: actions/setup-go@v6 with: go-version-file: go.mod @@ -54,7 +54,7 @@ jobs: timeout: 10m steps: - - uses: actions/checkout@v6.0.2 # Checkout complement + - uses: actions/checkout@v6.0.3 # Checkout complement - uses: actions/setup-go@v6 with: From 6173f055e6ded6eeb3bd819663bf4fdc0619840b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 20:36:27 +0000 Subject: [PATCH 7/7] Bump the minor-and-patches group across 1 directory with 2 updates (#876) Signed-off-by: dependabot[bot] --- go.mod | 8 ++++---- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index e5f2bdf8..a6140019 100644 --- a/go.mod +++ b/go.mod @@ -10,9 +10,9 @@ require ( github.com/matrix-org/gomatrixserverlib v0.0.0-20260506075950-c9c468727353 github.com/matrix-org/util v0.0.0-20221111132719-399730281e66 github.com/sirupsen/logrus v1.9.4 - github.com/tidwall/gjson v1.18.0 + github.com/tidwall/gjson v1.19.0 github.com/tidwall/sjson v1.2.5 - golang.org/x/crypto v0.50.0 + golang.org/x/crypto v0.53.0 golang.org/x/exp v0.0.0-20230905200255-921286631fa9 gonum.org/v1/plot v0.17.0 ) @@ -54,8 +54,8 @@ require ( go.opentelemetry.io/otel/sdk v1.43.0 // indirect go.opentelemetry.io/otel/trace v1.43.0 // indirect golang.org/x/image v0.38.0 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.36.0 // indirect + golang.org/x/sys v0.46.0 // indirect + golang.org/x/text v0.38.0 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect gonum.org/v1/gonum v0.17.0 // indirect gotest.tools/v3 v3.0.3 // indirect diff --git a/go.sum b/go.sum index 069ba5f4..ed3b3436 100644 --- a/go.sum +++ b/go.sum @@ -104,8 +104,8 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= -github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.19.0 h1:xwxm7n691Uf3u5OFjzngavjGTh55KX5q/9w9xHW88JU= +github.com/tidwall/gjson v1.19.0/go.mod h1:V37/opeE/JbLUOfH0QTXiNez2l0RUjYUhpT4szFQAfc= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= @@ -135,45 +135,45 @@ go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXd golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= +golang.org/x/crypto v0.53.0 h1:QZ4Muo8THX6CizN2vPPd5fBGHyogrdK9fG4wLPFUsto= +golang.org/x/crypto v0.53.0/go.mod h1:DNLU434OwVakk9PzuwV8w62mAJpRJL3vsgcfp4Qnsio= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.38.0 h1:5l+q+Y9JDC7mBOMjo4/aPhMDcxEptsX+Tt3GgRQRPuE= golang.org/x/image v0.38.0/go.mod h1:/3f6vaXC+6CEanU4KJxbcUZyEePbyKbaLoDOe4ehFYY= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.34.0 h1:xIHgNUUnW6sYkcM5Jleh05DvLOtwc6RitGHbDk4akRI= -golang.org/x/mod v0.34.0/go.mod h1:ykgH52iCZe79kzLLMhyCUzhMci+nQj+0XkbXpNYtVjY= +golang.org/x/mod v0.36.0 h1:JJjpVx6myfUsUdAzZuOSTTmRE0PfZeNWzzvKrP7amb4= +golang.org/x/mod v0.36.0/go.mod h1:moc6ELqsWcOw5Ef3xVprK5ul/MvtVvkIXLziUOICjUQ= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0= -golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw= +golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= +golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= +golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM= +golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= +golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/text v0.38.0 h1:sXmwo9DwP3OK9EZ7PqAdaooSGozfl/3a6/xJcbzPRhE= +golang.org/x/text v0.38.0/go.mod h1:YXZt3QhHUKYT53r2lLKFIVi6Ao1jdzrTR/KQ09qyxF4= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.43.0 h1:12BdW9CeB3Z+J/I/wj34VMl8X+fEXBxVR90JeMX5E7s= -golang.org/x/tools v0.43.0/go.mod h1:uHkMso649BX2cZK6+RpuIPXS3ho2hZo4FVwfoy1vIk0= +golang.org/x/tools v0.45.0 h1:18qN3FAooORvApf5XjCXgsuayZOEtXf6JK18I3+ONa8= +golang.org/x/tools v0.45.0/go.mod h1:LuUGqqaXcXMEFEruIVJVm5mgDD8vww/z/SR1gQ4uE/0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=