worryg0d commented on code in PR #1920:
URL:
https://github.com/apache/cassandra-gocql-driver/pull/1920#discussion_r2572104499
##########
protocol_negotiation_test.go:
##########
@@ -0,0 +1,179 @@
+//go:build all || unit
+// +build all unit
+
+package gocql
+
+import (
+ "context"
+ "encoding/binary"
+ "fmt"
+ "slices"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/require"
+)
+
+type requestHandlerForProtocolNegotiationTest struct {
+ supportedProtocolVersions []protoVersion
+ supportedBetaProtocols []protoVersion
+}
+
+func (r *requestHandlerForProtocolNegotiationTest)
supportsBetaProtocol(version protoVersion) bool {
+ return slices.Contains(r.supportedBetaProtocols, version)
+}
+
+func (r *requestHandlerForProtocolNegotiationTest) supportsProtocol(version
protoVersion) bool {
+ return slices.Contains(r.supportedProtocolVersions, version)
+}
+
+func (r *requestHandlerForProtocolNegotiationTest) hasBetaFlag(header
*frameHeader) bool {
+ return header.flags&flagBetaProtocol == flagBetaProtocol
+}
+
+func (r *requestHandlerForProtocolNegotiationTest)
createBetaFlagUnsetProtocolErrorMessage(version protoVersion) string {
+ return fmt.Sprintf("Beta version of the protocol used (%d/v%d-beta),
but USE_BETA flag is unset", version, version)
+}
+
+func (r *requestHandlerForProtocolNegotiationTest) handle(_ *TestServer,
reqFrame, respFrame *framer) error {
+ // If a client uses beta protocol, but the USE_BETA flag is not set, we
respond with an error
+ if r.supportsBetaProtocol(reqFrame.header.version) &&
!r.hasBetaFlag(reqFrame.header) {
+ respFrame.writeHeader(0, opError, reqFrame.header.stream)
+ respFrame.writeInt(ErrCodeProtocol)
+
respFrame.writeString(r.createBetaFlagUnsetProtocolErrorMessage(reqFrame.header.version))
+ return nil
+ }
+
+ // if a client uses an unsupported protocol version, we respond with an
error
+ if !r.supportsProtocol(reqFrame.header.version) {
+ respFrame.writeHeader(0, opError, reqFrame.header.stream)
+ respFrame.writeInt(ErrCodeProtocol)
+ respFrame.writeString(fmt.Sprintf("NEGOTITATION TEST:
Unsupported protocol version %d", reqFrame.header.version))
+ return nil
+ }
+
+ stream := reqFrame.header.stream
+
+ switch reqFrame.header.op {
+ case opStartup, opRegister:
+ respFrame.writeHeader(0, opReady, stream)
+ case opOptions:
+ respFrame.writeHeader(0, opSupported, stream)
+ var supportedVersionsWithDesc []string
+ for _, supportedVersion := range r.supportedProtocolVersions {
+ supportedVersionsWithDesc =
append(supportedVersionsWithDesc, fmt.Sprintf("%d/v%d", supportedVersion,
supportedVersion))
+ }
+ for _, betaProtocol := range r.supportedBetaProtocols {
+ supportedVersionsWithDesc =
append(supportedVersionsWithDesc, fmt.Sprintf("%d/v%d-beta", betaProtocol,
betaProtocol))
+ }
+ supported := map[string][]string{
+ "PROTOCOL_VERSIONS": supportedVersionsWithDesc,
+ }
+ respFrame.writeStringMultiMap(supported)
+ case opQuery:
+ respFrame.writeHeader(0, opResult, stream)
+ respFrame.writeInt(resultKindRows)
+ respFrame.writeInt(int32(flagGlobalTableSpec))
+ respFrame.writeInt(1)
+ respFrame.writeString("system")
+ respFrame.writeString("local")
+ respFrame.writeString("rack")
+ respFrame.writeShort(uint16(TypeVarchar))
+ respFrame.writeInt(1)
+ respFrame.writeInt(int32(len("rack-1")))
+ respFrame.writeString("rack-1")
+ case opPrepare:
+ // This doesn't really make any sense, but it's enough to test
the protocol negotiation
+ respFrame.writeHeader(0, opResult, stream)
+ respFrame.writeInt(resultKindPrepared)
+ // <id>
+ respFrame.writeShortBytes(binary.BigEndian.AppendUint64(nil,
111))
+ if respFrame.proto >= protoVersion5 {
+
respFrame.writeShortBytes(binary.BigEndian.AppendUint64(nil, 222))
+ }
+ // <metadata>
+ respFrame.writeInt(0) // <flags>
+ respFrame.writeInt(0) // <columns_count>
+ if reqFrame.header.version >= protoVersion4 {
+ respFrame.writeInt(0) // <pk_count>
+ }
+ // <result_metadata>
+ respFrame.writeInt(int32(flagGlobalTableSpec)) // <flags>
+ respFrame.writeInt(1) //
<columns_count>
+ // <global_table_spec>
+ respFrame.writeString("system")
+ respFrame.writeString("keyspaces")
+ // <col_spec_0>
+ respFrame.writeString("col0") // <name>
+ respFrame.writeShort(uint16(TypeBoolean)) // <type>
+ case opExecute:
+ // This doesn't really make any sense, but it's enough to test
the protocol negotiation
+ respFrame.writeHeader(0, opResult, stream)
+ respFrame.writeInt(resultKindRows)
+ // <metadata>
+ respFrame.writeInt(0) // <flags>
+ respFrame.writeInt(0) // <columns_count>
+ // <rows_count>
+ respFrame.writeInt(0)
+ }
+
+ return nil
+}
+
+func TestProtocolNegotiation(t *testing.T) {
Review Comment:
Thanks. I'll add verbose for unit tests to ci
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]