@@ -17,6 +17,8 @@ limitations under the License.
1717package mysqlctl
1818
1919import (
20+ "context"
21+ "net"
2022 "os"
2123 "strconv"
2224 "strings"
@@ -25,10 +27,14 @@ import (
2527
2628 "github.com/stretchr/testify/assert"
2729 "github.com/stretchr/testify/require"
30+ "google.golang.org/grpc"
2831
2932 "vitess.io/vitess/go/mysql/fakesqldb"
33+ "vitess.io/vitess/go/protoutil"
3034 "vitess.io/vitess/go/sqltypes"
3135 "vitess.io/vitess/go/vt/dbconfigs"
36+ _ "vitess.io/vitess/go/vt/mysqlctl/grpcmysqlctlclient"
37+ mysqlctlpb "vitess.io/vitess/go/vt/proto/mysqlctl"
3238)
3339
3440type testcase struct {
@@ -114,6 +120,70 @@ func TestParseVersionString(t *testing.T) {
114120 }
115121}
116122
123+ // shutdownRecordingMysqlCtlServer records remote Shutdown requests from Mysqld.
124+ type shutdownRecordingMysqlCtlServer struct {
125+ mysqlctlpb.UnimplementedMysqlCtlServer
126+
127+ // shutdownRequests carries the remote shutdown request.
128+ shutdownRequests chan * mysqlctlpb.ShutdownRequest
129+ }
130+
131+ // Shutdown records the request and returns a successful response.
132+ func (s * shutdownRecordingMysqlCtlServer ) Shutdown (ctx context.Context , request * mysqlctlpb.ShutdownRequest ) (* mysqlctlpb.ShutdownResponse , error ) {
133+ s .shutdownRequests <- request
134+
135+ return & mysqlctlpb.ShutdownResponse {}, nil
136+ }
137+
138+ // TestMysqldShutdownForwardsTimeoutToRemoteMysqlctld verifies that the remote
139+ // shutdown path preserves the caller's timeout.
140+ func TestMysqldShutdownForwardsTimeoutToRemoteMysqlctld (t * testing.T ) {
141+ ctx , cancel := context .WithTimeout (t .Context (), 5 * time .Second )
142+ t .Cleanup (cancel )
143+
144+ oldSocketFile := socketFile
145+ t .Cleanup (func () {
146+ socketFile = oldSocketFile
147+ })
148+
149+ tempSocketFile , err := os .CreateTemp ("/tmp" , "mysqlctld-*.sock" )
150+ require .NoError (t , err )
151+ require .NoError (t , tempSocketFile .Close ())
152+ require .NoError (t , os .Remove (tempSocketFile .Name ()))
153+ t .Cleanup (func () {
154+ _ = os .Remove (tempSocketFile .Name ())
155+ })
156+
157+ socketPath := tempSocketFile .Name ()
158+ listener , err := net .Listen ("unix" , socketPath )
159+ require .NoError (t , err )
160+
161+ server := grpc .NewServer ()
162+ t .Cleanup (server .Stop )
163+
164+ recordingServer := & shutdownRecordingMysqlCtlServer {
165+ shutdownRequests : make (chan * mysqlctlpb.ShutdownRequest , 1 ),
166+ }
167+ mysqlctlpb .RegisterMysqlCtlServer (server , recordingServer )
168+
169+ go func () { _ = server .Serve (listener ) }()
170+
171+ socketFile = socketPath
172+ shutdownTimeout := 43 * time .Second + 125 * time .Millisecond
173+
174+ mysqld := & Mysqld {}
175+ err = mysqld .Shutdown (ctx , & Mycnf {}, true , shutdownTimeout )
176+ require .NoError (t , err )
177+
178+ request := <- recordingServer .shutdownRequests
179+ assert .True (t , request .WaitForMysqld )
180+
181+ gotTimeout , ok , err := protoutil .DurationFromProto (request .MysqlShutdownTimeout )
182+ require .NoError (t , err )
183+ require .True (t , ok )
184+ assert .Equal (t , shutdownTimeout , gotTimeout )
185+ }
186+
117187func TestRegexps (t * testing.T ) {
118188 {
119189 submatch := binlogEntryTimestampGTIDRegexp .FindStringSubmatch (`#230608 13:14:31 server id 484362839 end_log_pos 259 CRC32 0xc07510d0 GTID last_committed=0 sequence_number=1 rbr_only=yes` )
0 commit comments