github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/message/query_test.go (about)

     1  // Copyright 2020 DataStax
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package message
    16  
    17  import (
    18  	"bytes"
    19  	"errors"
    20  	"testing"
    21  
    22  	"github.com/stretchr/testify/assert"
    23  
    24  	"github.com/datastax/go-cassandra-native-protocol/primitive"
    25  )
    26  
    27  func TestQuery_DeepCopy(t *testing.T) {
    28  	msg := &Query{
    29  		Query: "query",
    30  		Options: &QueryOptions{
    31  			Consistency: primitive.ConsistencyLevelAll,
    32  			PositionalValues: []*primitive.Value{
    33  				{
    34  					Type:     primitive.ValueTypeRegular,
    35  					Contents: []byte{0x11},
    36  				},
    37  			},
    38  			NamedValues: map[string]*primitive.Value{
    39  				"1": {
    40  					Type:     primitive.ValueTypeUnset,
    41  					Contents: []byte{0x21},
    42  				},
    43  			},
    44  			SkipMetadata:      false,
    45  			PageSize:          5,
    46  			PageSizeInBytes:   false,
    47  			PagingState:       []byte{0x33},
    48  			SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
    49  			DefaultTimestamp:  int64Ptr(1),
    50  			Keyspace:          "ks1",
    51  			NowInSeconds:      int32Ptr(3),
    52  			ContinuousPagingOptions: &ContinuousPagingOptions{
    53  				MaxPages:       5,
    54  				PagesPerSecond: 2,
    55  				NextPages:      3,
    56  			},
    57  		},
    58  	}
    59  
    60  	cloned := msg.DeepCopy()
    61  	assert.Equal(t, msg, cloned)
    62  
    63  	cloned.Query = "query 2"
    64  	cloned.Options = &QueryOptions{
    65  		Consistency: primitive.ConsistencyLevelLocalOne,
    66  		PositionalValues: []*primitive.Value{
    67  			{
    68  				Type:     primitive.ValueTypeUnset,
    69  				Contents: []byte{0x21},
    70  			},
    71  		},
    72  		NamedValues: map[string]*primitive.Value{
    73  			"1": {
    74  				Type:     primitive.ValueTypeNull,
    75  				Contents: []byte{0x31},
    76  			},
    77  		},
    78  		SkipMetadata:      true,
    79  		PageSize:          4,
    80  		PageSizeInBytes:   true,
    81  		PagingState:       []byte{0x23},
    82  		SerialConsistency: nil,
    83  		DefaultTimestamp:  int64Ptr(3),
    84  		Keyspace:          "ks2",
    85  		NowInSeconds:      nil,
    86  		ContinuousPagingOptions: &ContinuousPagingOptions{
    87  			MaxPages:       6,
    88  			PagesPerSecond: 3,
    89  			NextPages:      4,
    90  		},
    91  	}
    92  
    93  	assert.Equal(t, "query", msg.Query)
    94  	assert.Equal(t, primitive.ConsistencyLevelAll, msg.Options.Consistency)
    95  	assert.Equal(t, primitive.ValueTypeRegular, msg.Options.PositionalValues[0].Type)
    96  	assert.Equal(t, []byte{0x11}, msg.Options.PositionalValues[0].Contents)
    97  	assert.Equal(t, primitive.ValueTypeUnset, msg.Options.NamedValues["1"].Type)
    98  	assert.Equal(t, []byte{0x21}, msg.Options.NamedValues["1"].Contents)
    99  	assert.False(t, msg.Options.SkipMetadata)
   100  	assert.EqualValues(t, 5, msg.Options.PageSize)
   101  	assert.False(t, msg.Options.PageSizeInBytes)
   102  	assert.Equal(t, []byte{0x33}, msg.Options.PagingState)
   103  	assert.Equal(t, primitive.ConsistencyLevelLocalSerial, *msg.Options.SerialConsistency)
   104  	assert.EqualValues(t, 1, *msg.Options.DefaultTimestamp)
   105  	assert.Equal(t, "ks1", msg.Options.Keyspace)
   106  	assert.EqualValues(t, 3, *msg.Options.NowInSeconds)
   107  	assert.EqualValues(t, 5, msg.Options.ContinuousPagingOptions.MaxPages)
   108  	assert.EqualValues(t, 2, msg.Options.ContinuousPagingOptions.PagesPerSecond)
   109  	assert.EqualValues(t, 3, msg.Options.ContinuousPagingOptions.NextPages)
   110  
   111  	assert.NotEqual(t, msg, cloned)
   112  
   113  	assert.Equal(t, "query 2", cloned.Query)
   114  	assert.Equal(t, primitive.ConsistencyLevelLocalOne, cloned.Options.Consistency)
   115  	assert.Equal(t, primitive.ValueTypeUnset, cloned.Options.PositionalValues[0].Type)
   116  	assert.Equal(t, []byte{0x21}, cloned.Options.PositionalValues[0].Contents)
   117  	assert.Equal(t, primitive.ValueTypeNull, cloned.Options.NamedValues["1"].Type)
   118  	assert.Equal(t, []byte{0x31}, cloned.Options.NamedValues["1"].Contents)
   119  	assert.True(t, cloned.Options.SkipMetadata)
   120  	assert.EqualValues(t, 4, cloned.Options.PageSize)
   121  	assert.True(t, cloned.Options.PageSizeInBytes)
   122  	assert.Equal(t, []byte{0x23}, cloned.Options.PagingState)
   123  	assert.Nil(t, cloned.Options.SerialConsistency)
   124  	assert.EqualValues(t, 3, *cloned.Options.DefaultTimestamp)
   125  	assert.Equal(t, "ks2", cloned.Options.Keyspace)
   126  	assert.Nil(t, cloned.Options.NowInSeconds)
   127  	assert.EqualValues(t, 6, cloned.Options.ContinuousPagingOptions.MaxPages)
   128  	assert.EqualValues(t, 3, cloned.Options.ContinuousPagingOptions.PagesPerSecond)
   129  	assert.EqualValues(t, 4, cloned.Options.ContinuousPagingOptions.NextPages)
   130  }
   131  
   132  func TestQueryCodec_Encode(t *testing.T) {
   133  	codec := &queryCodec{}
   134  	// tests for version 2
   135  	t.Run(primitive.ProtocolVersion2.String(), func(t *testing.T) {
   136  		tests := []encodeTestCase{
   137  			{
   138  				"query with default options",
   139  				&Query{
   140  					Query:   "SELECT",
   141  					Options: &QueryOptions{},
   142  				},
   143  				[]byte{
   144  					0, 0, 0, 6, S, E, L, E, C, T,
   145  					0, 0, // consistency level
   146  					0, // flags
   147  				},
   148  				nil,
   149  			},
   150  			{
   151  				"query with custom options and no values",
   152  				&Query{
   153  					Query: "SELECT",
   154  					Options: &QueryOptions{
   155  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
   156  						SkipMetadata:      true,
   157  						PageSize:          100,
   158  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
   159  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   160  						DefaultTimestamp:  int64Ptr(123),
   161  					},
   162  				},
   163  				[]byte{
   164  					0, 0, 0, 6, S, E, L, E, C, T,
   165  					0, 6, // consistency level
   166  					0b0011_1110,  // flags
   167  					0, 0, 0, 100, // page size
   168  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
   169  					0, 9, // serial consistency level
   170  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
   171  				},
   172  				nil,
   173  			},
   174  			{
   175  				"query with positional values",
   176  				&Query{
   177  					Query: "SELECT",
   178  					Options: &QueryOptions{
   179  						PositionalValues: []*primitive.Value{
   180  							{
   181  								Type:     primitive.ValueTypeRegular,
   182  								Contents: []byte{h, e, l, l, o},
   183  							},
   184  							{
   185  								Type: primitive.ValueTypeNull,
   186  							},
   187  						},
   188  					},
   189  				},
   190  				[]byte{
   191  					0, 0, 0, 6, S, E, L, E, C, T,
   192  					0, 0, // consistency level
   193  					0b0000_0001, // flags
   194  					0, 2,        // values length
   195  					0, 0, 0, 5, h, e, l, l, o, // value 1
   196  					0xff, 0xff, 0xff, 0xff, // value 2
   197  				},
   198  				nil,
   199  			},
   200  			{
   201  				"query with named values",
   202  				&Query{
   203  					Query: "SELECT",
   204  					Options: &QueryOptions{
   205  						NamedValues: map[string]*primitive.Value{
   206  							"col1": {
   207  								Type:     primitive.ValueTypeRegular,
   208  								Contents: []byte{h, e, l, l, o},
   209  							},
   210  						},
   211  					},
   212  				},
   213  				[]byte{
   214  					0, 0, 0, 6, S, E, L, E, C, T,
   215  					0, 0, // consistency level
   216  					0b0100_0001, // flags
   217  					0, 1,        // values length
   218  					0, 4, c, o, l, _1, // name 1
   219  					0, 0, 0, 5, h, e, l, l, o, // value 1
   220  				},
   221  				nil,
   222  			},
   223  			{
   224  				"query with empty query string",
   225  				&Query{},
   226  				[]byte{
   227  					0, 0, 0, 0, // empty query
   228  					0, 0, // consistency level
   229  					0, // flags
   230  				},
   231  				nil,
   232  			},
   233  			{
   234  				"not a query",
   235  				&Options{},
   236  				nil,
   237  				errors.New("expected *message.Query, got *message.Options"),
   238  			},
   239  		}
   240  		for _, tt := range tests {
   241  			t.Run(tt.name, func(t *testing.T) {
   242  				dest := &bytes.Buffer{}
   243  				err := codec.Encode(tt.input, dest, primitive.ProtocolVersion2)
   244  				assert.Equal(t, tt.expected, dest.Bytes())
   245  				assert.Equal(t, tt.err, err)
   246  			})
   247  		}
   248  	})
   249  	// tests for version 3
   250  	t.Run(primitive.ProtocolVersion3.String(), func(t *testing.T) {
   251  		tests := []encodeTestCase{
   252  			{
   253  				"query with default options",
   254  				&Query{
   255  					Query:   "SELECT",
   256  					Options: &QueryOptions{},
   257  				},
   258  				[]byte{
   259  					0, 0, 0, 6, S, E, L, E, C, T,
   260  					0, 0, // consistency level
   261  					0, // flags
   262  				},
   263  				nil,
   264  			},
   265  			{
   266  				"query with custom options and no values",
   267  				&Query{
   268  					Query: "SELECT",
   269  					Options: &QueryOptions{
   270  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
   271  						SkipMetadata:      true,
   272  						PageSize:          100,
   273  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
   274  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   275  						DefaultTimestamp:  int64Ptr(123),
   276  					},
   277  				},
   278  				[]byte{
   279  					0, 0, 0, 6, S, E, L, E, C, T,
   280  					0, 6, // consistency level
   281  					0b0011_1110,  // flags
   282  					0, 0, 0, 100, // page size
   283  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
   284  					0, 9, // serial consistency level
   285  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
   286  				},
   287  				nil,
   288  			},
   289  			{
   290  				"query with positional values",
   291  				&Query{
   292  					Query: "SELECT",
   293  					Options: &QueryOptions{
   294  						PositionalValues: []*primitive.Value{
   295  							{
   296  								Type:     primitive.ValueTypeRegular,
   297  								Contents: []byte{h, e, l, l, o},
   298  							},
   299  							{
   300  								Type: primitive.ValueTypeNull,
   301  							},
   302  						},
   303  					},
   304  				},
   305  				[]byte{
   306  					0, 0, 0, 6, S, E, L, E, C, T,
   307  					0, 0, // consistency level
   308  					0b0000_0001, // flags
   309  					0, 2,        // values length
   310  					0, 0, 0, 5, h, e, l, l, o, // value 1
   311  					0xff, 0xff, 0xff, 0xff, // value 2
   312  				},
   313  				nil,
   314  			},
   315  			{
   316  				"query with named values",
   317  				&Query{
   318  					Query: "SELECT",
   319  					Options: &QueryOptions{
   320  						NamedValues: map[string]*primitive.Value{
   321  							"col1": {
   322  								Type:     primitive.ValueTypeRegular,
   323  								Contents: []byte{h, e, l, l, o},
   324  							},
   325  						},
   326  					},
   327  				},
   328  				[]byte{
   329  					0, 0, 0, 6, S, E, L, E, C, T,
   330  					0, 0, // consistency level
   331  					0b0100_0001, // flags
   332  					0, 1,        // values length
   333  					0, 4, c, o, l, _1, // name 1
   334  					0, 0, 0, 5, h, e, l, l, o, // value 1
   335  				},
   336  				nil,
   337  			},
   338  			{
   339  				"query with empty query string",
   340  				&Query{},
   341  				[]byte{
   342  					0, 0, 0, 0, // empty query
   343  					0, 0, // consistency level
   344  					0, // flags
   345  				},
   346  				nil,
   347  			},
   348  			{
   349  				"not a query",
   350  				&Options{},
   351  				nil,
   352  				errors.New("expected *message.Query, got *message.Options"),
   353  			},
   354  		}
   355  		for _, tt := range tests {
   356  			t.Run(tt.name, func(t *testing.T) {
   357  				dest := &bytes.Buffer{}
   358  				err := codec.Encode(tt.input, dest, primitive.ProtocolVersion3)
   359  				assert.Equal(t, tt.expected, dest.Bytes())
   360  				assert.Equal(t, tt.err, err)
   361  			})
   362  		}
   363  	})
   364  	// tests for version = 4
   365  	t.Run(primitive.ProtocolVersion4.String(), func(t *testing.T) {
   366  		tests := []struct {
   367  			name     string
   368  			input    Message
   369  			expected []byte
   370  			err      error
   371  		}{
   372  			{
   373  				"query with default options",
   374  				&Query{
   375  					Query:   "SELECT",
   376  					Options: &QueryOptions{},
   377  				},
   378  				[]byte{
   379  					0, 0, 0, 6, S, E, L, E, C, T,
   380  					0, 0, // consistency level
   381  					0, // flags
   382  				},
   383  				nil,
   384  			},
   385  			{
   386  				"query with custom options and no values",
   387  				&Query{
   388  					Query: "SELECT",
   389  					Options: &QueryOptions{
   390  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
   391  						SkipMetadata:      true,
   392  						PageSize:          100,
   393  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
   394  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   395  						DefaultTimestamp:  int64Ptr(123),
   396  					},
   397  				},
   398  				[]byte{
   399  					0, 0, 0, 6, S, E, L, E, C, T,
   400  					0, 6, // consistency level
   401  					0b0011_1110,  // flags
   402  					0, 0, 0, 100, // page size
   403  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
   404  					0, 9, // serial consistency level
   405  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
   406  				},
   407  				nil,
   408  			},
   409  			{
   410  				"query with positional values",
   411  				&Query{
   412  					Query: "SELECT",
   413  					Options: &QueryOptions{
   414  						PositionalValues: []*primitive.Value{
   415  							{
   416  								Type:     primitive.ValueTypeRegular,
   417  								Contents: []byte{h, e, l, l, o},
   418  							},
   419  							{
   420  								Type: primitive.ValueTypeNull,
   421  							},
   422  							{
   423  								Type: primitive.ValueTypeUnset,
   424  							},
   425  						},
   426  					},
   427  				},
   428  				[]byte{
   429  					0, 0, 0, 6, S, E, L, E, C, T,
   430  					0, 0, // consistency level
   431  					0b0000_0001, // flags
   432  					0, 3,        // values length
   433  					0, 0, 0, 5, h, e, l, l, o, // value 1
   434  					0xff, 0xff, 0xff, 0xff, // value 2
   435  					0xff, 0xff, 0xff, 0xfe, // value 3
   436  				},
   437  				nil,
   438  			},
   439  			{
   440  				"query with named values",
   441  				&Query{
   442  					Query: "SELECT",
   443  					Options: &QueryOptions{
   444  						NamedValues: map[string]*primitive.Value{
   445  							"col1": {
   446  								Type:     primitive.ValueTypeRegular,
   447  								Contents: []byte{h, e, l, l, o},
   448  							},
   449  						},
   450  					},
   451  				},
   452  				[]byte{
   453  					0, 0, 0, 6, S, E, L, E, C, T,
   454  					0, 0, // consistency level
   455  					0b0100_0001, // flags
   456  					0, 1,        // values length
   457  					0, 4, c, o, l, _1, // name 1
   458  					0, 0, 0, 5, h, e, l, l, o, // value 1
   459  				},
   460  				nil,
   461  			},
   462  			{
   463  				"query with empty query string",
   464  				&Query{},
   465  				[]byte{
   466  					0, 0, 0, 0, // empty query
   467  					0, 0, // consistency level
   468  					0, // flags
   469  				},
   470  				nil,
   471  			},
   472  			{
   473  				"not a query",
   474  				&Options{},
   475  				nil,
   476  				errors.New("expected *message.Query, got *message.Options"),
   477  			},
   478  		}
   479  		for _, tt := range tests {
   480  			t.Run(tt.name, func(t *testing.T) {
   481  				dest := &bytes.Buffer{}
   482  				err := codec.Encode(tt.input, dest, primitive.ProtocolVersion4)
   483  				assert.Equal(t, tt.expected, dest.Bytes())
   484  				assert.Equal(t, tt.err, err)
   485  			})
   486  		}
   487  	})
   488  	// tests for version = 5
   489  	t.Run(primitive.ProtocolVersion5.String(), func(t *testing.T) {
   490  		tests := []encodeTestCase{
   491  			{
   492  				"query with keyspace and now-in-seconds",
   493  				&Query{
   494  					Query: "SELECT",
   495  					Options: &QueryOptions{
   496  						Keyspace:     "ks1",
   497  						NowInSeconds: int32Ptr(123),
   498  					},
   499  				},
   500  				[]byte{
   501  					0, 0, 0, 6, S, E, L, E, C, T,
   502  					0, 0, // consistency level
   503  					0b0000_0000,    // flags
   504  					0b0000_0000,    // flags
   505  					0b0000_0001,    // flags (keyspace)
   506  					0b1000_0000,    // flags (now in seconds)
   507  					0, 3, k, s, _1, // keyspace
   508  					0, 0, 0, 123, // now in seconds
   509  				},
   510  				nil,
   511  			},
   512  			{
   513  				"query with positional values, keyspace and now-in-seconds",
   514  				&Query{
   515  					Query: "SELECT",
   516  					Options: &QueryOptions{
   517  						Keyspace:     "ks1",
   518  						NowInSeconds: int32Ptr(123),
   519  						PositionalValues: []*primitive.Value{
   520  							{
   521  								Type:     primitive.ValueTypeRegular,
   522  								Contents: []byte{h, e, l, l, o},
   523  							},
   524  							{
   525  								Type: primitive.ValueTypeNull,
   526  							},
   527  							{
   528  								Type: primitive.ValueTypeUnset,
   529  							},
   530  						},
   531  					},
   532  				},
   533  				[]byte{
   534  					0, 0, 0, 6, S, E, L, E, C, T,
   535  					0, 0, // consistency level
   536  					0b0000_0000, // flags
   537  					0b0000_0000, // flags
   538  					0b0000_0001, // flags
   539  					0b1000_0001, // flags
   540  					0, 3,        // values length
   541  					0, 0, 0, 5, h, e, l, l, o, // value 1
   542  					0xff, 0xff, 0xff, 0xff, // value 2
   543  					0xff, 0xff, 0xff, 0xfe, // value 3
   544  					0, 3, k, s, _1, // keyspace
   545  					0, 0, 0, 123, // now in seconds
   546  				},
   547  				nil,
   548  			},
   549  		}
   550  		for _, tt := range tests {
   551  			t.Run(tt.name, func(t *testing.T) {
   552  				dest := &bytes.Buffer{}
   553  				err := codec.Encode(tt.input, dest, primitive.ProtocolVersion5)
   554  				assert.Equal(t, tt.expected, dest.Bytes())
   555  				assert.Equal(t, tt.err, err)
   556  			})
   557  		}
   558  	})
   559  	// tests for version = DSE v1
   560  	t.Run(primitive.ProtocolVersionDse1.String(), func(t *testing.T) {
   561  		tests := []struct {
   562  			name     string
   563  			input    Message
   564  			expected []byte
   565  			err      error
   566  		}{
   567  			{
   568  				"query with default options",
   569  				&Query{
   570  					Query:   "SELECT",
   571  					Options: &QueryOptions{},
   572  				},
   573  				[]byte{
   574  					0, 0, 0, 6, S, E, L, E, C, T,
   575  					0, 0, // consistency level
   576  					0, 0, 0, 0, // flags
   577  				},
   578  				nil,
   579  			},
   580  			{
   581  				"query with custom options and no values",
   582  				&Query{
   583  					Query: "SELECT",
   584  					Options: &QueryOptions{
   585  						Consistency:             primitive.ConsistencyLevelLocalQuorum,
   586  						SkipMetadata:            true,
   587  						PageSize:                100,
   588  						PageSizeInBytes:         true,
   589  						PagingState:             []byte{0xca, 0xfe, 0xba, 0xbe},
   590  						SerialConsistency:       consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   591  						DefaultTimestamp:        int64Ptr(123),
   592  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10},
   593  					},
   594  				},
   595  				[]byte{
   596  					0, 0, 0, 6, S, E, L, E, C, T,
   597  					0, 6, // consistency level
   598  					0b1100_0000, 0, 0, 0b0011_1110, // flags
   599  					0, 0, 0, 100, // page size
   600  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
   601  					0, 9, // serial consistency level
   602  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
   603  					0, 0, 0, 50, // max pages
   604  					0, 0, 0, 10, // pages per sec
   605  				},
   606  				nil,
   607  			},
   608  			{
   609  				"query with positional values",
   610  				&Query{
   611  					Query: "SELECT",
   612  					Options: &QueryOptions{
   613  						PositionalValues: []*primitive.Value{
   614  							{
   615  								Type:     primitive.ValueTypeRegular,
   616  								Contents: []byte{h, e, l, l, o},
   617  							},
   618  							{
   619  								Type: primitive.ValueTypeNull,
   620  							},
   621  							{
   622  								Type: primitive.ValueTypeUnset,
   623  							},
   624  						},
   625  					},
   626  				},
   627  				[]byte{
   628  					0, 0, 0, 6, S, E, L, E, C, T,
   629  					0, 0, // consistency level
   630  					0, 0, 0, 0b0000_0001, // flags
   631  					0, 3, // values length
   632  					0, 0, 0, 5, h, e, l, l, o, // value 1
   633  					0xff, 0xff, 0xff, 0xff, // value 2
   634  					0xff, 0xff, 0xff, 0xfe, // value 3
   635  				},
   636  				nil,
   637  			},
   638  			{
   639  				"query with named values",
   640  				&Query{
   641  					Query: "SELECT",
   642  					Options: &QueryOptions{
   643  						NamedValues: map[string]*primitive.Value{
   644  							"col1": {
   645  								Type:     primitive.ValueTypeRegular,
   646  								Contents: []byte{h, e, l, l, o},
   647  							},
   648  						},
   649  					},
   650  				},
   651  				[]byte{
   652  					0, 0, 0, 6, S, E, L, E, C, T,
   653  					0, 0, // consistency level
   654  					0, 0, 0, 0b0100_0001, // flags
   655  					0, 1, // values length
   656  					0, 4, c, o, l, _1, // name 1
   657  					0, 0, 0, 5, h, e, l, l, o, // value 1
   658  				},
   659  				nil,
   660  			},
   661  			{
   662  				"query with empty query string",
   663  				&Query{},
   664  				[]byte{
   665  					0, 0, 0, 0, // empty query
   666  					0, 0, // consistency level
   667  					0, 0, 0, 0, // flags
   668  				},
   669  				nil,
   670  			},
   671  			{
   672  				"not a query",
   673  				&Options{},
   674  				nil,
   675  				errors.New("expected *message.Query, got *message.Options"),
   676  			},
   677  		}
   678  		for _, tt := range tests {
   679  			t.Run(tt.name, func(t *testing.T) {
   680  				dest := &bytes.Buffer{}
   681  				err := codec.Encode(tt.input, dest, primitive.ProtocolVersionDse1)
   682  				assert.Equal(t, tt.expected, dest.Bytes())
   683  				assert.Equal(t, tt.err, err)
   684  			})
   685  		}
   686  	})
   687  	// tests for version = DSE v2
   688  	t.Run(primitive.ProtocolVersionDse2.String(), func(t *testing.T) {
   689  		tests := []encodeTestCase{
   690  			{
   691  				"query with keyspace and continuous options",
   692  				&Query{
   693  					Query: "SELECT",
   694  					Options: &QueryOptions{
   695  						Keyspace:                "ks1",
   696  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10, NextPages: 20},
   697  					},
   698  				},
   699  				[]byte{
   700  					0, 0, 0, 6, S, E, L, E, C, T,
   701  					0, 0, // consistency level
   702  					0b1000_0000,    // flags (cont. paging)
   703  					0b0000_0000,    // flags
   704  					0b0000_0000,    // flags
   705  					0b1000_0000,    // flags (keyspace)
   706  					0, 3, k, s, _1, // keyspace
   707  					0, 0, 0, 50, // max pages
   708  					0, 0, 0, 10, // pages per sec
   709  					0, 0, 0, 20, // next pages
   710  				},
   711  				nil,
   712  			},
   713  			{
   714  				"query with custom options and no values",
   715  				&Query{
   716  					Query: "SELECT",
   717  					Options: &QueryOptions{
   718  						Consistency:             primitive.ConsistencyLevelLocalQuorum,
   719  						SkipMetadata:            true,
   720  						PageSize:                100,
   721  						PageSizeInBytes:         true,
   722  						PagingState:             []byte{0xca, 0xfe, 0xba, 0xbe},
   723  						SerialConsistency:       consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   724  						DefaultTimestamp:        int64Ptr(123),
   725  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10, NextPages: 20},
   726  					},
   727  				},
   728  				[]byte{
   729  					0, 0, 0, 6, S, E, L, E, C, T,
   730  					0, 6, // consistency level
   731  					0b1100_0000, 0, 0, 0b0011_1110, // flags
   732  					0, 0, 0, 100, // page size
   733  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
   734  					0, 9, // serial consistency level
   735  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
   736  					0, 0, 0, 50, // max pages
   737  					0, 0, 0, 10, // pages per sec
   738  					0, 0, 0, 20, // next pages
   739  				},
   740  				nil,
   741  			},
   742  			{
   743  				"query with positional values and keyspace",
   744  				&Query{
   745  					Query: "SELECT",
   746  					Options: &QueryOptions{
   747  						Keyspace: "ks1",
   748  						PositionalValues: []*primitive.Value{
   749  							{
   750  								Type:     primitive.ValueTypeRegular,
   751  								Contents: []byte{h, e, l, l, o},
   752  							},
   753  							{
   754  								Type: primitive.ValueTypeNull,
   755  							},
   756  							{
   757  								Type: primitive.ValueTypeUnset,
   758  							},
   759  						},
   760  					},
   761  				},
   762  				[]byte{
   763  					0, 0, 0, 6, S, E, L, E, C, T,
   764  					0, 0, // consistency level
   765  					0b0000_0000, // flags
   766  					0b0000_0000, // flags
   767  					0b0000_0000, // flags
   768  					0b1000_0001, // flags (keyspace | values)
   769  					0, 3,        // values length
   770  					0, 0, 0, 5, h, e, l, l, o, // value 1
   771  					0xff, 0xff, 0xff, 0xff, // value 2
   772  					0xff, 0xff, 0xff, 0xfe, // value 3
   773  					0, 3, k, s, _1, // keyspace
   774  				},
   775  				nil,
   776  			},
   777  		}
   778  		for _, tt := range tests {
   779  			t.Run(tt.name, func(t *testing.T) {
   780  				dest := &bytes.Buffer{}
   781  				err := codec.Encode(tt.input, dest, primitive.ProtocolVersionDse2)
   782  				assert.Equal(t, tt.expected, dest.Bytes())
   783  				assert.Equal(t, tt.err, err)
   784  			})
   785  		}
   786  	})
   787  }
   788  
   789  func TestQueryCodec_EncodedLength(t *testing.T) {
   790  	codec := &queryCodec{}
   791  	// tests for version 2
   792  	t.Run(primitive.ProtocolVersion2.String(), func(t *testing.T) {
   793  		tests := []encodedLengthTestCase{
   794  			{
   795  				"query with default options",
   796  				&Query{
   797  					Query:   "SELECT",
   798  					Options: &QueryOptions{},
   799  				},
   800  				primitive.LengthOfLongString("SELECT") +
   801  					primitive.LengthOfShort + // consistency
   802  					primitive.LengthOfByte, // flags
   803  				nil,
   804  			},
   805  			{
   806  				"query with custom options and no values",
   807  				&Query{
   808  					Query: "SELECT",
   809  					Options: &QueryOptions{
   810  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
   811  						SkipMetadata:      true,
   812  						PageSize:          100,
   813  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
   814  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   815  						DefaultTimestamp:  int64Ptr(123),
   816  					},
   817  				},
   818  				primitive.LengthOfLongString("SELECT") +
   819  					primitive.LengthOfShort + // consistency
   820  					primitive.LengthOfByte + // flags
   821  					primitive.LengthOfInt + // page size
   822  					primitive.LengthOfBytes([]byte{0xca, 0xfe, 0xba, 0xbe}) + // paging state
   823  					primitive.LengthOfShort + // serial consistency
   824  					primitive.LengthOfLong, // default timestamp
   825  				nil,
   826  			},
   827  			{
   828  				"query with positional values",
   829  				&Query{
   830  					Query: "SELECT",
   831  					Options: &QueryOptions{
   832  						PositionalValues: []*primitive.Value{
   833  							{
   834  								Type:     primitive.ValueTypeRegular,
   835  								Contents: []byte{h, e, l, l, o},
   836  							},
   837  							{
   838  								Type: primitive.ValueTypeNull,
   839  							},
   840  						},
   841  					},
   842  				},
   843  				primitive.LengthOfLongString("SELECT") +
   844  					primitive.LengthOfShort + // consistency
   845  					primitive.LengthOfByte + // flags
   846  					primitive.LengthOfShort + // values length
   847  					primitive.LengthOfBytes([]byte{h, e, l, l, o}) + // value 1
   848  					primitive.LengthOfInt, // value 2
   849  				nil,
   850  			},
   851  			{
   852  				"query with named values",
   853  				&Query{
   854  					Query: "SELECT",
   855  					Options: &QueryOptions{
   856  						NamedValues: map[string]*primitive.Value{
   857  							"col1": {
   858  								Type:     primitive.ValueTypeRegular,
   859  								Contents: []byte{h, e, l, l, o},
   860  							},
   861  						},
   862  					},
   863  				},
   864  				primitive.LengthOfLongString("SELECT") +
   865  					primitive.LengthOfShort + // consistency
   866  					primitive.LengthOfByte + // flags
   867  					primitive.LengthOfShort + // values length
   868  					primitive.LengthOfString("col1") + // name 1
   869  					primitive.LengthOfBytes([]byte{h, e, l, l, o}), // value 1
   870  				nil,
   871  			},
   872  			{
   873  				"not a query",
   874  				&Options{},
   875  				-1,
   876  				errors.New("expected *message.Query, got *message.Options"),
   877  			},
   878  		}
   879  		for _, tt := range tests {
   880  			t.Run(tt.name, func(t *testing.T) {
   881  				actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersion2)
   882  				assert.Equal(t, tt.expected, actual)
   883  				assert.Equal(t, tt.err, err)
   884  			})
   885  		}
   886  	})
   887  	// tests for version 3
   888  	t.Run(primitive.ProtocolVersion3.String(), func(t *testing.T) {
   889  		tests := []encodedLengthTestCase{
   890  			{
   891  				"query with default options",
   892  				&Query{
   893  					Query:   "SELECT",
   894  					Options: &QueryOptions{},
   895  				},
   896  				primitive.LengthOfLongString("SELECT") +
   897  					primitive.LengthOfShort + // consistency
   898  					primitive.LengthOfByte, // flags
   899  				nil,
   900  			},
   901  			{
   902  				"query with custom options and no values",
   903  				&Query{
   904  					Query: "SELECT",
   905  					Options: &QueryOptions{
   906  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
   907  						SkipMetadata:      true,
   908  						PageSize:          100,
   909  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
   910  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
   911  						DefaultTimestamp:  int64Ptr(123),
   912  					},
   913  				},
   914  				primitive.LengthOfLongString("SELECT") +
   915  					primitive.LengthOfShort + // consistency
   916  					primitive.LengthOfByte + // flags
   917  					primitive.LengthOfInt + // page size
   918  					primitive.LengthOfBytes([]byte{0xca, 0xfe, 0xba, 0xbe}) + // paging state
   919  					primitive.LengthOfShort + // serial consistency
   920  					primitive.LengthOfLong, // default timestamp
   921  				nil,
   922  			},
   923  			{
   924  				"query with positional values",
   925  				&Query{
   926  					Query: "SELECT",
   927  					Options: &QueryOptions{
   928  						PositionalValues: []*primitive.Value{
   929  							{
   930  								Type:     primitive.ValueTypeRegular,
   931  								Contents: []byte{h, e, l, l, o},
   932  							},
   933  							{
   934  								Type: primitive.ValueTypeNull,
   935  							},
   936  						},
   937  					},
   938  				},
   939  				primitive.LengthOfLongString("SELECT") +
   940  					primitive.LengthOfShort + // consistency
   941  					primitive.LengthOfByte + // flags
   942  					primitive.LengthOfShort + // values length
   943  					primitive.LengthOfBytes([]byte{h, e, l, l, o}) + // value 1
   944  					primitive.LengthOfInt, // value 2
   945  				nil,
   946  			},
   947  			{
   948  				"query with named values",
   949  				&Query{
   950  					Query: "SELECT",
   951  					Options: &QueryOptions{
   952  						NamedValues: map[string]*primitive.Value{
   953  							"col1": {
   954  								Type:     primitive.ValueTypeRegular,
   955  								Contents: []byte{h, e, l, l, o},
   956  							},
   957  						},
   958  					},
   959  				},
   960  				primitive.LengthOfLongString("SELECT") +
   961  					primitive.LengthOfShort + // consistency
   962  					primitive.LengthOfByte + // flags
   963  					primitive.LengthOfShort + // values length
   964  					primitive.LengthOfString("col1") + // name 1
   965  					primitive.LengthOfBytes([]byte{h, e, l, l, o}), // value 1
   966  				nil,
   967  			},
   968  			{
   969  				"not a query",
   970  				&Options{},
   971  				-1,
   972  				errors.New("expected *message.Query, got *message.Options"),
   973  			},
   974  		}
   975  		for _, tt := range tests {
   976  			t.Run(tt.name, func(t *testing.T) {
   977  				actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersion3)
   978  				assert.Equal(t, tt.expected, actual)
   979  				assert.Equal(t, tt.err, err)
   980  			})
   981  		}
   982  	})
   983  	// tests for version = 4
   984  	t.Run(primitive.ProtocolVersion4.String(), func(t *testing.T) {
   985  		tests := []struct {
   986  			name     string
   987  			input    Message
   988  			expected int
   989  			err      error
   990  		}{
   991  			{
   992  				"query with default options",
   993  				&Query{
   994  					Query:   "SELECT",
   995  					Options: &QueryOptions{},
   996  				},
   997  				primitive.LengthOfLongString("SELECT") +
   998  					primitive.LengthOfShort + // consistency
   999  					primitive.LengthOfByte, // flags
  1000  				nil,
  1001  			},
  1002  			{
  1003  				"query with custom options and no values",
  1004  				&Query{
  1005  					Query: "SELECT",
  1006  					Options: &QueryOptions{
  1007  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
  1008  						SkipMetadata:      true,
  1009  						PageSize:          100,
  1010  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
  1011  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1012  						DefaultTimestamp:  int64Ptr(123),
  1013  					},
  1014  				},
  1015  				primitive.LengthOfLongString("SELECT") +
  1016  					primitive.LengthOfShort + // consistency
  1017  					primitive.LengthOfByte + // flags
  1018  					primitive.LengthOfInt + // page size
  1019  					primitive.LengthOfBytes([]byte{0xca, 0xfe, 0xba, 0xbe}) + // paging state
  1020  					primitive.LengthOfShort + // serial consistency
  1021  					primitive.LengthOfLong, // default timestamp
  1022  				nil,
  1023  			},
  1024  			{
  1025  				"query with positional values",
  1026  				&Query{
  1027  					Query: "SELECT",
  1028  					Options: &QueryOptions{
  1029  						PositionalValues: []*primitive.Value{
  1030  							{
  1031  								Type:     primitive.ValueTypeRegular,
  1032  								Contents: []byte{h, e, l, l, o},
  1033  							},
  1034  							{
  1035  								Type: primitive.ValueTypeNull,
  1036  							},
  1037  							{
  1038  								Type: primitive.ValueTypeUnset,
  1039  							},
  1040  						},
  1041  					},
  1042  				},
  1043  				primitive.LengthOfLongString("SELECT") +
  1044  					primitive.LengthOfShort + // consistency
  1045  					primitive.LengthOfByte + // flags
  1046  					primitive.LengthOfShort + // values length
  1047  					primitive.LengthOfBytes([]byte{h, e, l, l, o}) + // value 1
  1048  					primitive.LengthOfInt + // value 2
  1049  					primitive.LengthOfInt, // value 3
  1050  				nil,
  1051  			},
  1052  			{
  1053  				"query with named values",
  1054  				&Query{
  1055  					Query: "SELECT",
  1056  					Options: &QueryOptions{
  1057  						NamedValues: map[string]*primitive.Value{
  1058  							"col1": {
  1059  								Type:     primitive.ValueTypeRegular,
  1060  								Contents: []byte{h, e, l, l, o},
  1061  							},
  1062  						},
  1063  					},
  1064  				},
  1065  				primitive.LengthOfLongString("SELECT") +
  1066  					primitive.LengthOfShort + // consistency
  1067  					primitive.LengthOfByte + // flags
  1068  					primitive.LengthOfShort + // values length
  1069  					primitive.LengthOfString("col1") + // name 1
  1070  					primitive.LengthOfBytes([]byte{h, e, l, l, o}), // value 1
  1071  				nil,
  1072  			},
  1073  			{
  1074  				"not a query",
  1075  				&Options{},
  1076  				-1,
  1077  				errors.New("expected *message.Query, got *message.Options"),
  1078  			},
  1079  		}
  1080  		for _, tt := range tests {
  1081  			t.Run(tt.name, func(t *testing.T) {
  1082  				actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersion4)
  1083  				assert.Equal(t, tt.expected, actual)
  1084  				assert.Equal(t, tt.err, err)
  1085  			})
  1086  		}
  1087  	})
  1088  	// tests for version = 5
  1089  	t.Run(primitive.ProtocolVersion5.String(), func(t *testing.T) {
  1090  		tests := []encodedLengthTestCase{
  1091  			{
  1092  				"query with keyspace and now-in-seconds",
  1093  				&Query{
  1094  					Query: "SELECT",
  1095  					Options: &QueryOptions{
  1096  						Keyspace:     "ks1",
  1097  						NowInSeconds: int32Ptr(123),
  1098  					},
  1099  				},
  1100  				primitive.LengthOfLongString("SELECT") +
  1101  					primitive.LengthOfShort + // consistency
  1102  					primitive.LengthOfInt + // flags
  1103  					primitive.LengthOfString("ks1") + // keyspace
  1104  					primitive.LengthOfInt, // new in seconds
  1105  				nil,
  1106  			},
  1107  			{
  1108  				"query with positional values, keyspace and now-in-seconds",
  1109  				&Query{
  1110  					Query: "SELECT",
  1111  					Options: &QueryOptions{
  1112  						Keyspace:     "ks1",
  1113  						NowInSeconds: int32Ptr(123),
  1114  						PositionalValues: []*primitive.Value{
  1115  							{
  1116  								Type:     primitive.ValueTypeRegular,
  1117  								Contents: []byte{h, e, l, l, o},
  1118  							},
  1119  							{
  1120  								Type: primitive.ValueTypeNull,
  1121  							},
  1122  							{
  1123  								Type: primitive.ValueTypeUnset,
  1124  							},
  1125  						},
  1126  					},
  1127  				},
  1128  				primitive.LengthOfLongString("SELECT") +
  1129  					primitive.LengthOfShort + // consistency
  1130  					primitive.LengthOfInt + // flags
  1131  					primitive.LengthOfShort + // values length
  1132  					primitive.LengthOfBytes([]byte{h, e, l, l, o}) + // value 1
  1133  					primitive.LengthOfInt + // value 2
  1134  					primitive.LengthOfInt + // value 3
  1135  					primitive.LengthOfString("ks1") + // keyspace
  1136  					primitive.LengthOfInt, // new in seconds
  1137  				nil,
  1138  			},
  1139  		}
  1140  		for _, tt := range tests {
  1141  			t.Run(tt.name, func(t *testing.T) {
  1142  				actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersion5)
  1143  				assert.Equal(t, tt.expected, actual)
  1144  				assert.Equal(t, tt.err, err)
  1145  			})
  1146  		}
  1147  	})
  1148  	// tests for version = DSE v1
  1149  	t.Run(primitive.ProtocolVersionDse1.String(), func(t *testing.T) {
  1150  		tests := []struct {
  1151  			name     string
  1152  			input    Message
  1153  			expected int
  1154  			err      error
  1155  		}{
  1156  			{
  1157  				"query with default options",
  1158  				&Query{
  1159  					Query:   "SELECT",
  1160  					Options: &QueryOptions{},
  1161  				},
  1162  				primitive.LengthOfLongString("SELECT") +
  1163  					primitive.LengthOfShort + // consistency
  1164  					primitive.LengthOfInt, // flags
  1165  				nil,
  1166  			},
  1167  			{
  1168  				"query with custom options and no values",
  1169  				&Query{
  1170  					Query: "SELECT",
  1171  					Options: &QueryOptions{
  1172  						Consistency:             primitive.ConsistencyLevelLocalQuorum,
  1173  						SkipMetadata:            true,
  1174  						PageSize:                100,
  1175  						PagingState:             []byte{0xca, 0xfe, 0xba, 0xbe},
  1176  						SerialConsistency:       consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1177  						DefaultTimestamp:        int64Ptr(123),
  1178  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10},
  1179  					},
  1180  				},
  1181  				primitive.LengthOfLongString("SELECT") +
  1182  					primitive.LengthOfShort + // consistency
  1183  					primitive.LengthOfInt + // flags
  1184  					primitive.LengthOfInt + // page size
  1185  					primitive.LengthOfBytes([]byte{0xca, 0xfe, 0xba, 0xbe}) + // paging state
  1186  					primitive.LengthOfShort + // serial consistency
  1187  					primitive.LengthOfLong + // default timestamp
  1188  					primitive.LengthOfInt*2, // cont. paging options
  1189  				nil,
  1190  			},
  1191  			{
  1192  				"query with positional values",
  1193  				&Query{
  1194  					Query: "SELECT",
  1195  					Options: &QueryOptions{
  1196  						PositionalValues: []*primitive.Value{
  1197  							{
  1198  								Type:     primitive.ValueTypeRegular,
  1199  								Contents: []byte{h, e, l, l, o},
  1200  							},
  1201  							{
  1202  								Type: primitive.ValueTypeNull,
  1203  							},
  1204  							{
  1205  								Type: primitive.ValueTypeUnset,
  1206  							},
  1207  						},
  1208  					},
  1209  				},
  1210  				primitive.LengthOfLongString("SELECT") +
  1211  					primitive.LengthOfShort + // consistency
  1212  					primitive.LengthOfInt + // flags
  1213  					primitive.LengthOfShort + // values length
  1214  					primitive.LengthOfBytes([]byte{h, e, l, l, o}) + // value 1
  1215  					primitive.LengthOfInt + // value 2
  1216  					primitive.LengthOfInt, // value 3
  1217  				nil,
  1218  			},
  1219  			{
  1220  				"query with named values",
  1221  				&Query{
  1222  					Query: "SELECT",
  1223  					Options: &QueryOptions{
  1224  						NamedValues: map[string]*primitive.Value{
  1225  							"col1": {
  1226  								Type:     primitive.ValueTypeRegular,
  1227  								Contents: []byte{h, e, l, l, o},
  1228  							},
  1229  						},
  1230  					},
  1231  				},
  1232  				primitive.LengthOfLongString("SELECT") +
  1233  					primitive.LengthOfShort + // consistency
  1234  					primitive.LengthOfInt + // flags
  1235  					primitive.LengthOfShort + // values length
  1236  					primitive.LengthOfString("col1") + // name 1
  1237  					primitive.LengthOfBytes([]byte{h, e, l, l, o}), // value 1
  1238  				nil,
  1239  			},
  1240  			{
  1241  				"not a query",
  1242  				&Options{},
  1243  				-1,
  1244  				errors.New("expected *message.Query, got *message.Options"),
  1245  			},
  1246  		}
  1247  		for _, tt := range tests {
  1248  			t.Run(tt.name, func(t *testing.T) {
  1249  				actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersionDse1)
  1250  				assert.Equal(t, tt.expected, actual)
  1251  				assert.Equal(t, tt.err, err)
  1252  			})
  1253  		}
  1254  	})
  1255  	// tests for version = DSE v2
  1256  	t.Run(primitive.ProtocolVersionDse2.String(), func(t *testing.T) {
  1257  		tests := []encodedLengthTestCase{
  1258  			{
  1259  				"query with keyspace",
  1260  				&Query{
  1261  					Query: "SELECT",
  1262  					Options: &QueryOptions{
  1263  						Keyspace:                "ks1",
  1264  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10, NextPages: 20},
  1265  					},
  1266  				},
  1267  				primitive.LengthOfLongString("SELECT") +
  1268  					primitive.LengthOfShort + // consistency
  1269  					primitive.LengthOfInt + // flags
  1270  					primitive.LengthOfString("ks1") + // keyspace
  1271  					primitive.LengthOfInt*3, // cont. paging options
  1272  				nil,
  1273  			},
  1274  			{
  1275  				"query with positional values and keyspace",
  1276  				&Query{
  1277  					Query: "SELECT",
  1278  					Options: &QueryOptions{
  1279  						Keyspace: "ks1",
  1280  						PositionalValues: []*primitive.Value{
  1281  							{
  1282  								Type:     primitive.ValueTypeRegular,
  1283  								Contents: []byte{h, e, l, l, o},
  1284  							},
  1285  							{
  1286  								Type: primitive.ValueTypeNull,
  1287  							},
  1288  							{
  1289  								Type: primitive.ValueTypeUnset,
  1290  							},
  1291  						},
  1292  					},
  1293  				},
  1294  				primitive.LengthOfLongString("SELECT") +
  1295  					primitive.LengthOfShort + // consistency
  1296  					primitive.LengthOfInt + // flags
  1297  					primitive.LengthOfShort + // values length
  1298  					primitive.LengthOfBytes([]byte{h, e, l, l, o}) + // value 1
  1299  					primitive.LengthOfInt + // value 2
  1300  					primitive.LengthOfInt + // value 3
  1301  					primitive.LengthOfString("ks1"), // keyspace
  1302  				nil,
  1303  			},
  1304  		}
  1305  		for _, tt := range tests {
  1306  			t.Run(tt.name, func(t *testing.T) {
  1307  				actual, err := codec.EncodedLength(tt.input, primitive.ProtocolVersionDse2)
  1308  				assert.Equal(t, tt.expected, actual)
  1309  				assert.Equal(t, tt.err, err)
  1310  			})
  1311  		}
  1312  	})
  1313  }
  1314  
  1315  func TestQueryCodec_Decode(t *testing.T) {
  1316  	codec := &queryCodec{}
  1317  	// tests for version 2
  1318  	t.Run(primitive.ProtocolVersion2.String(), func(t *testing.T) {
  1319  		tests := []decodeTestCase{
  1320  			{
  1321  				"query with default options",
  1322  				[]byte{
  1323  					0, 0, 0, 6, S, E, L, E, C, T,
  1324  					0, 0, // consistency level
  1325  					0, // flags
  1326  				},
  1327  				&Query{
  1328  					Query:   "SELECT",
  1329  					Options: &QueryOptions{},
  1330  				},
  1331  				nil,
  1332  			},
  1333  			{
  1334  				"query with custom options and no values",
  1335  				[]byte{
  1336  					0, 0, 0, 6, S, E, L, E, C, T,
  1337  					0, 6, // consistency level
  1338  					0b0011_1110,  // flags
  1339  					0, 0, 0, 100, // page size
  1340  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
  1341  					0, 9, // serial consistency level
  1342  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
  1343  				},
  1344  				&Query{
  1345  					Query: "SELECT",
  1346  					Options: &QueryOptions{
  1347  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
  1348  						SkipMetadata:      true,
  1349  						PageSize:          100,
  1350  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
  1351  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1352  						DefaultTimestamp:  int64Ptr(123),
  1353  					},
  1354  				},
  1355  				nil,
  1356  			},
  1357  			{
  1358  				"query with positional values",
  1359  				[]byte{
  1360  					0, 0, 0, 6, S, E, L, E, C, T,
  1361  					0, 0, // consistency level
  1362  					0b0000_0001, // flags
  1363  					0, 2,        // values length
  1364  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1365  					0xff, 0xff, 0xff, 0xff, // value 2
  1366  				},
  1367  				&Query{
  1368  					Query: "SELECT",
  1369  					Options: &QueryOptions{
  1370  						PositionalValues: []*primitive.Value{
  1371  							{
  1372  								Type:     primitive.ValueTypeRegular,
  1373  								Contents: []byte{h, e, l, l, o},
  1374  							},
  1375  							{
  1376  								Type: primitive.ValueTypeNull,
  1377  							},
  1378  						},
  1379  					},
  1380  				},
  1381  				nil,
  1382  			},
  1383  			{
  1384  				"query with named values",
  1385  				[]byte{
  1386  					0, 0, 0, 6, S, E, L, E, C, T,
  1387  					0, 0, // consistency level
  1388  					0b0100_0001, // flags
  1389  					0, 1,        // values length
  1390  					0, 4, c, o, l, _1, // name 1
  1391  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1392  				},
  1393  				&Query{
  1394  					Query: "SELECT",
  1395  					Options: &QueryOptions{
  1396  						NamedValues: map[string]*primitive.Value{
  1397  							"col1": {
  1398  								Type:     primitive.ValueTypeRegular,
  1399  								Contents: []byte{h, e, l, l, o},
  1400  							},
  1401  						},
  1402  					},
  1403  				},
  1404  				nil,
  1405  			},
  1406  			{
  1407  				"query with empty query string",
  1408  				[]byte{
  1409  					0, 0, 0, 0, // empty query
  1410  					0, 0, // consistency level
  1411  					0, // flags
  1412  				},
  1413  				&Query{
  1414  					Query:   "",
  1415  					Options: &QueryOptions{},
  1416  				},
  1417  				nil,
  1418  			},
  1419  		}
  1420  		for _, tt := range tests {
  1421  			t.Run(tt.name, func(t *testing.T) {
  1422  				source := bytes.NewBuffer(tt.input)
  1423  				actual, err := codec.Decode(source, primitive.ProtocolVersion2)
  1424  				assert.Equal(t, tt.expected, actual)
  1425  				assert.Equal(t, tt.err, err)
  1426  			})
  1427  		}
  1428  	})
  1429  	// tests for version 3
  1430  	t.Run(primitive.ProtocolVersion3.String(), func(t *testing.T) {
  1431  		tests := []decodeTestCase{
  1432  			{
  1433  				"query with default options",
  1434  				[]byte{
  1435  					0, 0, 0, 6, S, E, L, E, C, T,
  1436  					0, 0, // consistency level
  1437  					0, // flags
  1438  				},
  1439  				&Query{
  1440  					Query:   "SELECT",
  1441  					Options: &QueryOptions{},
  1442  				},
  1443  				nil,
  1444  			},
  1445  			{
  1446  				"query with custom options and no values",
  1447  				[]byte{
  1448  					0, 0, 0, 6, S, E, L, E, C, T,
  1449  					0, 6, // consistency level
  1450  					0b0011_1110,  // flags
  1451  					0, 0, 0, 100, // page size
  1452  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
  1453  					0, 9, // serial consistency level
  1454  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
  1455  				},
  1456  				&Query{
  1457  					Query: "SELECT",
  1458  					Options: &QueryOptions{
  1459  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
  1460  						SkipMetadata:      true,
  1461  						PageSize:          100,
  1462  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
  1463  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1464  						DefaultTimestamp:  int64Ptr(123),
  1465  					},
  1466  				},
  1467  				nil,
  1468  			},
  1469  			{
  1470  				"query with positional values",
  1471  				[]byte{
  1472  					0, 0, 0, 6, S, E, L, E, C, T,
  1473  					0, 0, // consistency level
  1474  					0b0000_0001, // flags
  1475  					0, 2,        // values length
  1476  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1477  					0xff, 0xff, 0xff, 0xff, // value 2
  1478  				},
  1479  				&Query{
  1480  					Query: "SELECT",
  1481  					Options: &QueryOptions{
  1482  						PositionalValues: []*primitive.Value{
  1483  							{
  1484  								Type:     primitive.ValueTypeRegular,
  1485  								Contents: []byte{h, e, l, l, o},
  1486  							},
  1487  							{
  1488  								Type: primitive.ValueTypeNull,
  1489  							},
  1490  						},
  1491  					},
  1492  				},
  1493  				nil,
  1494  			},
  1495  			{
  1496  				"query with named values",
  1497  				[]byte{
  1498  					0, 0, 0, 6, S, E, L, E, C, T,
  1499  					0, 0, // consistency level
  1500  					0b0100_0001, // flags
  1501  					0, 1,        // values length
  1502  					0, 4, c, o, l, _1, // name 1
  1503  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1504  				},
  1505  				&Query{
  1506  					Query: "SELECT",
  1507  					Options: &QueryOptions{
  1508  						NamedValues: map[string]*primitive.Value{
  1509  							"col1": {
  1510  								Type:     primitive.ValueTypeRegular,
  1511  								Contents: []byte{h, e, l, l, o},
  1512  							},
  1513  						},
  1514  					},
  1515  				},
  1516  				nil,
  1517  			},
  1518  			{
  1519  				"query with empty query string",
  1520  				[]byte{
  1521  					0, 0, 0, 0, // empty query
  1522  					0, 0, // consistency level
  1523  					0, // flags
  1524  				},
  1525  				&Query{
  1526  					Query:   "",
  1527  					Options: &QueryOptions{},
  1528  				},
  1529  				nil,
  1530  			},
  1531  		}
  1532  		for _, tt := range tests {
  1533  			t.Run(tt.name, func(t *testing.T) {
  1534  				source := bytes.NewBuffer(tt.input)
  1535  				actual, err := codec.Decode(source, primitive.ProtocolVersion3)
  1536  				assert.Equal(t, tt.expected, actual)
  1537  				assert.Equal(t, tt.err, err)
  1538  			})
  1539  		}
  1540  	})
  1541  	// tests for version = 4
  1542  	t.Run(primitive.ProtocolVersion4.String(), func(t *testing.T) {
  1543  		tests := []struct {
  1544  			name     string
  1545  			input    []byte
  1546  			expected Message
  1547  			err      error
  1548  		}{
  1549  			{
  1550  				"query with default options",
  1551  				[]byte{
  1552  					0, 0, 0, 6, S, E, L, E, C, T,
  1553  					0, 0, // consistency level
  1554  					0, // flags
  1555  				},
  1556  				&Query{
  1557  					Query:   "SELECT",
  1558  					Options: &QueryOptions{},
  1559  				},
  1560  				nil,
  1561  			},
  1562  			{
  1563  				"query with custom options and no values",
  1564  				[]byte{
  1565  					0, 0, 0, 6, S, E, L, E, C, T,
  1566  					0, 6, // consistency level
  1567  					0b0011_1110,  // flags
  1568  					0, 0, 0, 100, // page size
  1569  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
  1570  					0, 9, // serial consistency level
  1571  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
  1572  				},
  1573  				&Query{
  1574  					Query: "SELECT",
  1575  					Options: &QueryOptions{
  1576  						Consistency:       primitive.ConsistencyLevelLocalQuorum,
  1577  						SkipMetadata:      true,
  1578  						PageSize:          100,
  1579  						PagingState:       []byte{0xca, 0xfe, 0xba, 0xbe},
  1580  						SerialConsistency: consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1581  						DefaultTimestamp:  int64Ptr(123),
  1582  					},
  1583  				},
  1584  				nil,
  1585  			},
  1586  			{
  1587  				"query with positional values",
  1588  				[]byte{
  1589  					0, 0, 0, 6, S, E, L, E, C, T,
  1590  					0, 0, // consistency level
  1591  					0b0000_0001, // flags
  1592  					0, 3,        // values length
  1593  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1594  					0xff, 0xff, 0xff, 0xff, // value 2
  1595  					0xff, 0xff, 0xff, 0xfe, // value 3
  1596  				},
  1597  				&Query{
  1598  					Query: "SELECT",
  1599  					Options: &QueryOptions{
  1600  						PositionalValues: []*primitive.Value{
  1601  							{
  1602  								Type:     primitive.ValueTypeRegular,
  1603  								Contents: []byte{h, e, l, l, o},
  1604  							},
  1605  							{
  1606  								Type: primitive.ValueTypeNull,
  1607  							},
  1608  							{
  1609  								Type: primitive.ValueTypeUnset,
  1610  							},
  1611  						},
  1612  					},
  1613  				},
  1614  				nil,
  1615  			},
  1616  			{
  1617  				"query with named values",
  1618  				[]byte{
  1619  					0, 0, 0, 6, S, E, L, E, C, T,
  1620  					0, 0, // consistency level
  1621  					0b0100_0001, // flags
  1622  					0, 1,        // values length
  1623  					0, 4, c, o, l, _1, // name 1
  1624  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1625  				},
  1626  				&Query{
  1627  					Query: "SELECT",
  1628  					Options: &QueryOptions{
  1629  						NamedValues: map[string]*primitive.Value{
  1630  							"col1": {
  1631  								Type:     primitive.ValueTypeRegular,
  1632  								Contents: []byte{h, e, l, l, o},
  1633  							},
  1634  						},
  1635  					},
  1636  				},
  1637  				nil,
  1638  			},
  1639  			{
  1640  				"query with empty query string",
  1641  				[]byte{
  1642  					0, 0, 0, 0, // empty query
  1643  					0, 0, // consistency level
  1644  					0, // flags
  1645  				},
  1646  				&Query{
  1647  					Query:   "",
  1648  					Options: &QueryOptions{},
  1649  				},
  1650  				nil,
  1651  			},
  1652  		}
  1653  		for _, tt := range tests {
  1654  			t.Run(tt.name, func(t *testing.T) {
  1655  				source := bytes.NewBuffer(tt.input)
  1656  				actual, err := codec.Decode(source, primitive.ProtocolVersion4)
  1657  				assert.Equal(t, tt.expected, actual)
  1658  				assert.Equal(t, tt.err, err)
  1659  			})
  1660  		}
  1661  	})
  1662  	// tests for version = 5
  1663  	t.Run(primitive.ProtocolVersion5.String(), func(t *testing.T) {
  1664  		tests := []decodeTestCase{
  1665  			{
  1666  				"query with keyspace and now-in-seconds",
  1667  				[]byte{
  1668  					0, 0, 0, 6, S, E, L, E, C, T,
  1669  					0, 0, // consistency level
  1670  					0b0000_0000,    // flags
  1671  					0b0000_0000,    // flags
  1672  					0b0000_0001,    // flags (keyspace)
  1673  					0b1000_0000,    // flags (now in seconds)
  1674  					0, 3, k, s, _1, // keyspace
  1675  					0, 0, 0, 123, // now in seconds
  1676  				},
  1677  				&Query{
  1678  					Query: "SELECT",
  1679  					Options: &QueryOptions{
  1680  						Keyspace:     "ks1",
  1681  						NowInSeconds: int32Ptr(123),
  1682  					},
  1683  				},
  1684  				nil,
  1685  			},
  1686  			{
  1687  				"query with positional values, keyspace and now-in-seconds",
  1688  				[]byte{
  1689  					0, 0, 0, 6, S, E, L, E, C, T,
  1690  					0, 0, // consistency level
  1691  					0b0000_0000, // flags
  1692  					0b0000_0000, // flags
  1693  					0b0000_0001, // flags
  1694  					0b1000_0001, // flags
  1695  					0, 3,        // values length
  1696  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1697  					0xff, 0xff, 0xff, 0xff, // value 2
  1698  					0xff, 0xff, 0xff, 0xfe, // value 3
  1699  					0, 3, k, s, _1, // keyspace
  1700  					0, 0, 0, 123, // now in seconds
  1701  				},
  1702  				&Query{
  1703  					Query: "SELECT",
  1704  					Options: &QueryOptions{
  1705  						Keyspace:     "ks1",
  1706  						NowInSeconds: int32Ptr(123),
  1707  						PositionalValues: []*primitive.Value{
  1708  							{
  1709  								Type:     primitive.ValueTypeRegular,
  1710  								Contents: []byte{h, e, l, l, o},
  1711  							},
  1712  							{
  1713  								Type: primitive.ValueTypeNull,
  1714  							},
  1715  							{
  1716  								Type: primitive.ValueTypeUnset,
  1717  							},
  1718  						},
  1719  					},
  1720  				},
  1721  				nil,
  1722  			},
  1723  		}
  1724  		for _, tt := range tests {
  1725  			t.Run(tt.name, func(t *testing.T) {
  1726  				source := bytes.NewBuffer(tt.input)
  1727  				actual, err := codec.Decode(source, primitive.ProtocolVersion5)
  1728  				assert.Equal(t, tt.expected, actual)
  1729  				assert.Equal(t, tt.err, err)
  1730  			})
  1731  		}
  1732  	})
  1733  	// tests for version = DSE v1
  1734  	t.Run(primitive.ProtocolVersionDse1.String(), func(t *testing.T) {
  1735  		tests := []struct {
  1736  			name     string
  1737  			input    []byte
  1738  			expected Message
  1739  			err      error
  1740  		}{
  1741  			{
  1742  				"query with default options",
  1743  				[]byte{
  1744  					0, 0, 0, 6, S, E, L, E, C, T,
  1745  					0, 0, // consistency level
  1746  					0, 0, 0, 0, // flags
  1747  				},
  1748  				&Query{
  1749  					Query:   "SELECT",
  1750  					Options: &QueryOptions{},
  1751  				},
  1752  				nil,
  1753  			},
  1754  			{
  1755  				"query with custom options and no values",
  1756  				[]byte{
  1757  					0, 0, 0, 6, S, E, L, E, C, T,
  1758  					0, 6, // consistency level
  1759  					0b1100_0000, 0, 0, 0b0011_1110, // flags (cont. paging and page size bytes)
  1760  					0, 0, 0, 100, // page size
  1761  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
  1762  					0, 9, // serial consistency level
  1763  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
  1764  					0, 0, 0, 50, // max pages
  1765  					0, 0, 0, 10, // pages per sec
  1766  				},
  1767  				&Query{
  1768  					Query: "SELECT",
  1769  					Options: &QueryOptions{
  1770  						Consistency:             primitive.ConsistencyLevelLocalQuorum,
  1771  						SkipMetadata:            true,
  1772  						PageSize:                100,
  1773  						PageSizeInBytes:         true,
  1774  						PagingState:             []byte{0xca, 0xfe, 0xba, 0xbe},
  1775  						SerialConsistency:       consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1776  						DefaultTimestamp:        int64Ptr(123),
  1777  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10},
  1778  					},
  1779  				},
  1780  				nil,
  1781  			},
  1782  			{
  1783  				"query with positional values",
  1784  				[]byte{
  1785  					0, 0, 0, 6, S, E, L, E, C, T,
  1786  					0, 0, // consistency level
  1787  					0, 0, 0, 0b0000_0001, // flags
  1788  					0, 3, // values length
  1789  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1790  					0xff, 0xff, 0xff, 0xff, // value 2
  1791  					0xff, 0xff, 0xff, 0xfe, // value 3
  1792  				},
  1793  				&Query{
  1794  					Query: "SELECT",
  1795  					Options: &QueryOptions{
  1796  						PositionalValues: []*primitive.Value{
  1797  							{
  1798  								Type:     primitive.ValueTypeRegular,
  1799  								Contents: []byte{h, e, l, l, o},
  1800  							},
  1801  							{
  1802  								Type: primitive.ValueTypeNull,
  1803  							},
  1804  							{
  1805  								Type: primitive.ValueTypeUnset,
  1806  							},
  1807  						},
  1808  					},
  1809  				},
  1810  				nil,
  1811  			},
  1812  			{
  1813  				"query with named values",
  1814  				[]byte{
  1815  					0, 0, 0, 6, S, E, L, E, C, T,
  1816  					0, 0, // consistency level
  1817  					0, 0, 0, 0b0100_0001, // flags
  1818  					0, 1, // values length
  1819  					0, 4, c, o, l, _1, // name 1
  1820  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1821  				},
  1822  				&Query{
  1823  					Query: "SELECT",
  1824  					Options: &QueryOptions{
  1825  						NamedValues: map[string]*primitive.Value{
  1826  							"col1": {
  1827  								Type:     primitive.ValueTypeRegular,
  1828  								Contents: []byte{h, e, l, l, o},
  1829  							},
  1830  						},
  1831  					},
  1832  				},
  1833  				nil,
  1834  			},
  1835  			{
  1836  				"query with empty query string",
  1837  				[]byte{
  1838  					0, 0, 0, 0, // empty query
  1839  					0, 0, // consistency level
  1840  					0, 0, 0, 0, // flags
  1841  				},
  1842  				&Query{
  1843  					Query:   "",
  1844  					Options: &QueryOptions{},
  1845  				},
  1846  				nil,
  1847  			},
  1848  		}
  1849  		for _, tt := range tests {
  1850  			t.Run(tt.name, func(t *testing.T) {
  1851  				source := bytes.NewBuffer(tt.input)
  1852  				actual, err := codec.Decode(source, primitive.ProtocolVersionDse1)
  1853  				assert.Equal(t, tt.expected, actual)
  1854  				assert.Equal(t, tt.err, err)
  1855  			})
  1856  		}
  1857  	})
  1858  	// tests for version = DSE v2
  1859  	t.Run(primitive.ProtocolVersionDse2.String(), func(t *testing.T) {
  1860  		tests := []decodeTestCase{
  1861  			{
  1862  				"query with keyspace and continuous paging",
  1863  				[]byte{
  1864  					0, 0, 0, 6, S, E, L, E, C, T,
  1865  					0, 0, // consistency level
  1866  					0b1000_0000,    // flags (cont. paging)
  1867  					0b0000_0000,    // flags
  1868  					0b0000_0000,    // flags
  1869  					0b1000_0000,    // flags (keyspace)
  1870  					0, 3, k, s, _1, // keyspace
  1871  					0, 0, 0, 50, // max pages
  1872  					0, 0, 0, 10, // pages per sec
  1873  					0, 0, 0, 20, // next pages
  1874  				},
  1875  				&Query{
  1876  					Query: "SELECT",
  1877  					Options: &QueryOptions{
  1878  						Keyspace:                "ks1",
  1879  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10, NextPages: 20},
  1880  					},
  1881  				},
  1882  				nil,
  1883  			},
  1884  			{
  1885  				"query with custom options and no values",
  1886  				[]byte{
  1887  					0, 0, 0, 6, S, E, L, E, C, T,
  1888  					0, 6, // consistency level
  1889  					0b1100_0000, 0, 0, 0b0011_1110, // flags
  1890  					0, 0, 0, 100, // page size
  1891  					0, 0, 0, 4, 0xca, 0xfe, 0xba, 0xbe, // paging state
  1892  					0, 9, // serial consistency level
  1893  					0, 0, 0, 0, 0, 0, 0, 123, // default timestamp
  1894  					0, 0, 0, 50, // max pages
  1895  					0, 0, 0, 10, // pages per sec
  1896  					0, 0, 0, 20, // next pages
  1897  				},
  1898  				&Query{
  1899  					Query: "SELECT",
  1900  					Options: &QueryOptions{
  1901  						Consistency:             primitive.ConsistencyLevelLocalQuorum,
  1902  						SkipMetadata:            true,
  1903  						PageSize:                100,
  1904  						PageSizeInBytes:         true,
  1905  						PagingState:             []byte{0xca, 0xfe, 0xba, 0xbe},
  1906  						SerialConsistency:       consistencyLevelPtr(primitive.ConsistencyLevelLocalSerial),
  1907  						DefaultTimestamp:        int64Ptr(123),
  1908  						ContinuousPagingOptions: &ContinuousPagingOptions{MaxPages: 50, PagesPerSecond: 10, NextPages: 20},
  1909  					},
  1910  				},
  1911  				nil,
  1912  			},
  1913  			{
  1914  				"query with positional values and keyspace",
  1915  				[]byte{
  1916  					0, 0, 0, 6, S, E, L, E, C, T,
  1917  					0, 0, // consistency level
  1918  					0b0000_0000, // flags
  1919  					0b0000_0000, // flags
  1920  					0b0000_0000, // flags
  1921  					0b1000_0001, // flags (keyspace | values)
  1922  					0, 3,        // values length
  1923  					0, 0, 0, 5, h, e, l, l, o, // value 1
  1924  					0xff, 0xff, 0xff, 0xff, // value 2
  1925  					0xff, 0xff, 0xff, 0xfe, // value 3
  1926  					0, 3, k, s, _1, // keyspace
  1927  				},
  1928  				&Query{
  1929  					Query: "SELECT",
  1930  					Options: &QueryOptions{
  1931  						Keyspace: "ks1",
  1932  						PositionalValues: []*primitive.Value{
  1933  							{
  1934  								Type:     primitive.ValueTypeRegular,
  1935  								Contents: []byte{h, e, l, l, o},
  1936  							},
  1937  							{
  1938  								Type: primitive.ValueTypeNull,
  1939  							},
  1940  							{
  1941  								Type: primitive.ValueTypeUnset,
  1942  							},
  1943  						},
  1944  					},
  1945  				},
  1946  				nil,
  1947  			},
  1948  		}
  1949  		for _, tt := range tests {
  1950  			t.Run(tt.name, func(t *testing.T) {
  1951  				source := bytes.NewBuffer(tt.input)
  1952  				actual, err := codec.Decode(source, primitive.ProtocolVersionDse2)
  1953  				assert.Equal(t, tt.expected, actual)
  1954  				assert.Equal(t, tt.err, err)
  1955  			})
  1956  		}
  1957  	})
  1958  }