conn_test.go 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  1. // Copyright (c) 2012 The gocql Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. // +build all unit
  5. package gocql
  6. import (
  7. "bufio"
  8. "bytes"
  9. "context"
  10. "crypto/tls"
  11. "crypto/x509"
  12. "fmt"
  13. "io"
  14. "io/ioutil"
  15. "net"
  16. "os"
  17. "strings"
  18. "sync"
  19. "sync/atomic"
  20. "testing"
  21. "time"
  22. "github.com/gocql/gocql/internal/streams"
  23. )
  24. const (
  25. defaultProto = protoVersion2
  26. )
  27. func TestApprove(t *testing.T) {
  28. tests := map[bool]bool{
  29. approve("org.apache.cassandra.auth.PasswordAuthenticator"): true,
  30. approve("com.instaclustr.cassandra.auth.SharedSecretAuthenticator"): true,
  31. approve("com.datastax.bdp.cassandra.auth.DseAuthenticator"): true,
  32. approve("com.apache.cassandra.auth.FakeAuthenticator"): false,
  33. }
  34. for k, v := range tests {
  35. if k != v {
  36. t.Fatalf("expected '%v', got '%v'", k, v)
  37. }
  38. }
  39. }
  40. func TestJoinHostPort(t *testing.T) {
  41. tests := map[string]string{
  42. "127.0.0.1:0": JoinHostPort("127.0.0.1", 0),
  43. "127.0.0.1:1": JoinHostPort("127.0.0.1:1", 9142),
  44. "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:0": JoinHostPort("2001:0db8:85a3:0000:0000:8a2e:0370:7334", 0),
  45. "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1": JoinHostPort("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:1", 9142),
  46. }
  47. for k, v := range tests {
  48. if k != v {
  49. t.Fatalf("expected '%v', got '%v'", k, v)
  50. }
  51. }
  52. }
  53. func testCluster(addr string, proto protoVersion) *ClusterConfig {
  54. cluster := NewCluster(addr)
  55. cluster.ProtoVersion = int(proto)
  56. cluster.disableControlConn = true
  57. return cluster
  58. }
  59. func TestSimple(t *testing.T) {
  60. srv := NewTestServer(t, defaultProto, context.Background())
  61. defer srv.Stop()
  62. cluster := testCluster(srv.Address, defaultProto)
  63. db, err := cluster.CreateSession()
  64. if err != nil {
  65. t.Fatalf("0x%x: NewCluster: %v", defaultProto, err)
  66. }
  67. if err := db.Query("void").Exec(); err != nil {
  68. t.Fatalf("0x%x: %v", defaultProto, err)
  69. }
  70. }
  71. func TestSSLSimple(t *testing.T) {
  72. srv := NewSSLTestServer(t, defaultProto, context.Background())
  73. defer srv.Stop()
  74. db, err := createTestSslCluster(srv.Address, defaultProto, true).CreateSession()
  75. if err != nil {
  76. t.Fatalf("0x%x: NewCluster: %v", defaultProto, err)
  77. }
  78. if err := db.Query("void").Exec(); err != nil {
  79. t.Fatalf("0x%x: %v", defaultProto, err)
  80. }
  81. }
  82. func TestSSLSimpleNoClientCert(t *testing.T) {
  83. srv := NewSSLTestServer(t, defaultProto, context.Background())
  84. defer srv.Stop()
  85. db, err := createTestSslCluster(srv.Address, defaultProto, false).CreateSession()
  86. if err != nil {
  87. t.Fatalf("0x%x: NewCluster: %v", defaultProto, err)
  88. }
  89. if err := db.Query("void").Exec(); err != nil {
  90. t.Fatalf("0x%x: %v", defaultProto, err)
  91. }
  92. }
  93. func createTestSslCluster(addr string, proto protoVersion, useClientCert bool) *ClusterConfig {
  94. cluster := testCluster(addr, proto)
  95. sslOpts := &SslOptions{
  96. CaPath: "testdata/pki/ca.crt",
  97. EnableHostVerification: false,
  98. }
  99. if useClientCert {
  100. sslOpts.CertPath = "testdata/pki/gocql.crt"
  101. sslOpts.KeyPath = "testdata/pki/gocql.key"
  102. }
  103. cluster.SslOpts = sslOpts
  104. return cluster
  105. }
  106. func TestClosed(t *testing.T) {
  107. t.Skip("Skipping the execution of TestClosed for now to try to concentrate on more important test failures on Travis")
  108. srv := NewTestServer(t, defaultProto, context.Background())
  109. defer srv.Stop()
  110. session, err := newTestSession(srv.Address, defaultProto)
  111. if err != nil {
  112. t.Fatalf("0x%x: NewCluster: %v", defaultProto, err)
  113. }
  114. session.Close()
  115. if err := session.Query("void").Exec(); err != ErrSessionClosed {
  116. t.Fatalf("0x%x: expected %#v, got %#v", defaultProto, ErrSessionClosed, err)
  117. }
  118. }
  119. func newTestSession(addr string, proto protoVersion) (*Session, error) {
  120. return testCluster(addr, proto).CreateSession()
  121. }
  122. func TestDNSLookupConnected(t *testing.T) {
  123. log := &testLogger{}
  124. Logger = log
  125. defer func() {
  126. Logger = &defaultLogger{}
  127. }()
  128. // Override the defaul DNS resolver and restore at the end
  129. failDNS = true
  130. defer func() { failDNS = false }()
  131. srv := NewTestServer(t, defaultProto, context.Background())
  132. defer srv.Stop()
  133. cluster := NewCluster("cassandra1.invalid", srv.Address, "cassandra2.invalid")
  134. cluster.ProtoVersion = int(defaultProto)
  135. cluster.disableControlConn = true
  136. // CreateSession() should attempt to resolve the DNS name "cassandraX.invalid"
  137. // and fail, but continue to connect via srv.Address
  138. _, err := cluster.CreateSession()
  139. if err != nil {
  140. t.Fatal("CreateSession() should have connected")
  141. }
  142. if !strings.Contains(log.String(), "gocql: dns error") {
  143. t.Fatalf("Expected to receive dns error log message - got '%s' instead", log.String())
  144. }
  145. }
  146. func TestDNSLookupError(t *testing.T) {
  147. log := &testLogger{}
  148. Logger = log
  149. defer func() {
  150. Logger = &defaultLogger{}
  151. }()
  152. // Override the defaul DNS resolver and restore at the end
  153. failDNS = true
  154. defer func() { failDNS = false }()
  155. cluster := NewCluster("cassandra1.invalid", "cassandra2.invalid")
  156. cluster.ProtoVersion = int(defaultProto)
  157. cluster.disableControlConn = true
  158. // CreateSession() should attempt to resolve each DNS name "cassandraX.invalid"
  159. // and fail since it could not resolve any dns entries
  160. _, err := cluster.CreateSession()
  161. if err == nil {
  162. t.Fatal("CreateSession() should have returned an error")
  163. }
  164. if !strings.Contains(log.String(), "gocql: dns error") {
  165. t.Fatalf("Expected to receive dns error log message - got '%s' instead", log.String())
  166. }
  167. if err.Error() != "gocql: unable to create session: failed to resolve any of the provided hostnames" {
  168. t.Fatalf("Expected CreateSession() to fail with message - got '%s' instead", err.Error())
  169. }
  170. }
  171. func TestStartupTimeout(t *testing.T) {
  172. ctx, cancel := context.WithCancel(context.Background())
  173. log := &testLogger{}
  174. Logger = log
  175. defer func() {
  176. Logger = &defaultLogger{}
  177. }()
  178. srv := NewTestServer(t, defaultProto, ctx)
  179. defer srv.Stop()
  180. // Tell the server to never respond to Startup frame
  181. atomic.StoreInt32(&srv.TimeoutOnStartup, 1)
  182. startTime := time.Now()
  183. cluster := NewCluster(srv.Address)
  184. cluster.ProtoVersion = int(defaultProto)
  185. cluster.disableControlConn = true
  186. // Set very long query connection timeout
  187. // so we know CreateSession() is using the ConnectTimeout
  188. cluster.Timeout = time.Second * 5
  189. // Create session should timeout during connect attempt
  190. _, err := cluster.CreateSession()
  191. if err == nil {
  192. t.Fatal("CreateSession() should have returned a timeout error")
  193. }
  194. elapsed := time.Since(startTime)
  195. if elapsed > time.Second*5 {
  196. t.Fatal("ConnectTimeout is not respected")
  197. }
  198. if !strings.Contains(err.Error(), "no connections were made when creating the session") {
  199. t.Fatalf("Expected to receive no connections error - got '%s'", err)
  200. }
  201. if !strings.Contains(log.String(), "no response to connection startup within timeout") {
  202. t.Fatalf("Expected to receive timeout log message - got '%s'", log.String())
  203. }
  204. cancel()
  205. }
  206. func TestTimeout(t *testing.T) {
  207. ctx, cancel := context.WithCancel(context.Background())
  208. srv := NewTestServer(t, defaultProto, ctx)
  209. defer srv.Stop()
  210. db, err := newTestSession(srv.Address, defaultProto)
  211. if err != nil {
  212. t.Fatalf("NewCluster: %v", err)
  213. }
  214. defer db.Close()
  215. var wg sync.WaitGroup
  216. wg.Add(1)
  217. go func() {
  218. defer wg.Done()
  219. select {
  220. case <-time.After(5 * time.Second):
  221. t.Errorf("no timeout")
  222. case <-ctx.Done():
  223. }
  224. }()
  225. if err := db.Query("kill").WithContext(ctx).Exec(); err == nil {
  226. t.Fatal("expected error got nil")
  227. }
  228. cancel()
  229. wg.Wait()
  230. }
  231. type testRetryPolicy struct {
  232. numRetries int // maximum number of times to retry a query
  233. attemptTimeout time.Duration
  234. t *testing.T
  235. }
  236. // Attempt tells gocql to attempt the query again based on query.Attempts being less
  237. // than the NumRetries defined in the policy.
  238. func (s *testRetryPolicy) Attempt(q RetryableQuery) bool {
  239. return q.Attempts() <= s.numRetries
  240. }
  241. func (s *testRetryPolicy) GetRetryType(err error) RetryType {
  242. return Retry
  243. }
  244. // AttemptTimeout satisfies the optional RetryPolicyWithAttemptTimeout interface.
  245. func (s *testRetryPolicy) AttemptTimeout() time.Duration {
  246. return s.attemptTimeout
  247. }
  248. type testQueryObserver struct{}
  249. func (o *testQueryObserver) ObserveQuery(ctx context.Context, q ObservedQuery) {
  250. Logger.Printf("Observed query %q. Returned %v rows, took %v on host %q. Error: %q\n", q.Statement, q.Rows, q.End.Sub(q.Start), q.Host.ConnectAddress().String(), q.Err)
  251. }
  252. // TestQueryRetry will test to make sure that gocql will execute
  253. // the exact amount of retry queries designated by the user.
  254. func TestQueryRetry(t *testing.T) {
  255. ctx, cancel := context.WithCancel(context.Background())
  256. defer cancel()
  257. log := &testLogger{}
  258. Logger = log
  259. defer func() {
  260. Logger = &defaultLogger{}
  261. os.Stdout.WriteString(log.String())
  262. }()
  263. srv := NewTestServer(t, defaultProto, ctx)
  264. defer srv.Stop()
  265. db, err := newTestSession(srv.Address, defaultProto)
  266. if err != nil {
  267. t.Fatalf("NewCluster: %v", err)
  268. }
  269. defer db.Close()
  270. go func() {
  271. select {
  272. case <-ctx.Done():
  273. return
  274. case <-time.After(5 * time.Second):
  275. t.Errorf("no timeout")
  276. }
  277. }()
  278. rt := &testRetryPolicy{numRetries: 2, t: t, attemptTimeout: time.Millisecond * 25}
  279. queryCtx, cancel := context.WithTimeout(context.Background(), time.Millisecond*90)
  280. defer cancel()
  281. qry := db.Query("slow").RetryPolicy(rt).Observer(&testQueryObserver{}).WithContext(queryCtx)
  282. if err := qry.Exec(); err == nil {
  283. t.Fatalf("expected error")
  284. }
  285. // wait for the last slow query to finish
  286. // this prevents the test from flaking because of writing to a connection that's been closed
  287. time.Sleep(100 * time.Millisecond)
  288. numQueries := atomic.LoadUint64(&srv.nQueries)
  289. // the 90ms timeout allows at most 4 retries but the maximum is 2 as per the retry policy
  290. // the number of queries therefore needs to be 3 (initial query + 2 retries)
  291. if numQueries != 3 {
  292. t.Fatalf("Number of queries should be 3 but query executed %v times", numQueries)
  293. }
  294. }
  295. func TestStreams_Protocol1(t *testing.T) {
  296. srv := NewTestServer(t, protoVersion1, context.Background())
  297. defer srv.Stop()
  298. // TODO: these are more like session tests and should instead operate
  299. // on a single Conn
  300. cluster := testCluster(srv.Address, protoVersion1)
  301. cluster.NumConns = 1
  302. cluster.ProtoVersion = 1
  303. db, err := cluster.CreateSession()
  304. if err != nil {
  305. t.Fatal(err)
  306. }
  307. defer db.Close()
  308. var wg sync.WaitGroup
  309. for i := 1; i < 128; i++ {
  310. // here were just validating that if we send NumStream request we get
  311. // a response for every stream and the lengths for the queries are set
  312. // correctly.
  313. wg.Add(1)
  314. go func() {
  315. defer wg.Done()
  316. if err := db.Query("void").Exec(); err != nil {
  317. t.Error(err)
  318. }
  319. }()
  320. }
  321. wg.Wait()
  322. }
  323. func TestStreams_Protocol3(t *testing.T) {
  324. srv := NewTestServer(t, protoVersion3, context.Background())
  325. defer srv.Stop()
  326. // TODO: these are more like session tests and should instead operate
  327. // on a single Conn
  328. cluster := testCluster(srv.Address, protoVersion3)
  329. cluster.NumConns = 1
  330. cluster.ProtoVersion = 3
  331. db, err := cluster.CreateSession()
  332. if err != nil {
  333. t.Fatal(err)
  334. }
  335. defer db.Close()
  336. for i := 1; i < 32768; i++ {
  337. // the test server processes each conn synchronously
  338. // here were just validating that if we send NumStream request we get
  339. // a response for every stream and the lengths for the queries are set
  340. // correctly.
  341. if err = db.Query("void").Exec(); err != nil {
  342. t.Fatal(err)
  343. }
  344. }
  345. }
  346. func BenchmarkProtocolV3(b *testing.B) {
  347. srv := NewTestServer(b, protoVersion3, context.Background())
  348. defer srv.Stop()
  349. // TODO: these are more like session tests and should instead operate
  350. // on a single Conn
  351. cluster := NewCluster(srv.Address)
  352. cluster.NumConns = 1
  353. cluster.ProtoVersion = 3
  354. db, err := cluster.CreateSession()
  355. if err != nil {
  356. b.Fatal(err)
  357. }
  358. defer db.Close()
  359. b.ResetTimer()
  360. b.ReportAllocs()
  361. for i := 0; i < b.N; i++ {
  362. if err = db.Query("void").Exec(); err != nil {
  363. b.Fatal(err)
  364. }
  365. }
  366. }
  367. // This tests that the policy connection pool handles SSL correctly
  368. func TestPolicyConnPoolSSL(t *testing.T) {
  369. srv := NewSSLTestServer(t, defaultProto, context.Background())
  370. defer srv.Stop()
  371. cluster := createTestSslCluster(srv.Address, defaultProto, true)
  372. cluster.PoolConfig.HostSelectionPolicy = RoundRobinHostPolicy()
  373. db, err := cluster.CreateSession()
  374. if err != nil {
  375. t.Fatalf("failed to create new session: %v", err)
  376. }
  377. if err := db.Query("void").Exec(); err != nil {
  378. t.Fatalf("query failed due to error: %v", err)
  379. }
  380. db.Close()
  381. // wait for the pool to drain
  382. time.Sleep(100 * time.Millisecond)
  383. size := db.pool.Size()
  384. if size != 0 {
  385. t.Fatalf("connection pool did not drain, still contains %d connections", size)
  386. }
  387. }
  388. func TestQueryTimeout(t *testing.T) {
  389. srv := NewTestServer(t, defaultProto, context.Background())
  390. defer srv.Stop()
  391. cluster := testCluster(srv.Address, defaultProto)
  392. // Set the timeout arbitrarily low so that the query hits the timeout in a
  393. // timely manner.
  394. cluster.Timeout = 1 * time.Millisecond
  395. db, err := cluster.CreateSession()
  396. if err != nil {
  397. t.Fatalf("NewCluster: %v", err)
  398. }
  399. defer db.Close()
  400. ch := make(chan error, 1)
  401. go func() {
  402. err := db.Query("timeout").Exec()
  403. if err != nil {
  404. ch <- err
  405. return
  406. }
  407. t.Errorf("err was nil, expected to get a timeout after %v", db.cfg.Timeout)
  408. }()
  409. select {
  410. case err := <-ch:
  411. if err != ErrTimeoutNoResponse {
  412. t.Fatalf("expected to get %v for timeout got %v", ErrTimeoutNoResponse, err)
  413. }
  414. case <-time.After(10*time.Millisecond + db.cfg.Timeout):
  415. // ensure that the query goroutines have been scheduled
  416. t.Fatalf("query did not timeout after %v", db.cfg.Timeout)
  417. }
  418. }
  419. func BenchmarkSingleConn(b *testing.B) {
  420. srv := NewTestServer(b, 3, context.Background())
  421. defer srv.Stop()
  422. cluster := testCluster(srv.Address, 3)
  423. // Set the timeout arbitrarily low so that the query hits the timeout in a
  424. // timely manner.
  425. cluster.Timeout = 500 * time.Millisecond
  426. cluster.NumConns = 1
  427. db, err := cluster.CreateSession()
  428. if err != nil {
  429. b.Fatalf("NewCluster: %v", err)
  430. }
  431. defer db.Close()
  432. b.ResetTimer()
  433. b.RunParallel(func(pb *testing.PB) {
  434. for pb.Next() {
  435. err := db.Query("void").Exec()
  436. if err != nil {
  437. b.Error(err)
  438. return
  439. }
  440. }
  441. })
  442. }
  443. func TestQueryTimeoutReuseStream(t *testing.T) {
  444. t.Skip("no longer tests anything")
  445. // TODO(zariel): move this to conn test, we really just want to check what
  446. // happens when a conn is
  447. srv := NewTestServer(t, defaultProto, context.Background())
  448. defer srv.Stop()
  449. cluster := testCluster(srv.Address, defaultProto)
  450. // Set the timeout arbitrarily low so that the query hits the timeout in a
  451. // timely manner.
  452. cluster.Timeout = 1 * time.Millisecond
  453. cluster.NumConns = 1
  454. db, err := cluster.CreateSession()
  455. if err != nil {
  456. t.Fatalf("NewCluster: %v", err)
  457. }
  458. defer db.Close()
  459. db.Query("slow").Exec()
  460. err = db.Query("void").Exec()
  461. if err != nil {
  462. t.Fatal(err)
  463. }
  464. }
  465. func TestQueryTimeoutClose(t *testing.T) {
  466. srv := NewTestServer(t, defaultProto, context.Background())
  467. defer srv.Stop()
  468. cluster := testCluster(srv.Address, defaultProto)
  469. // Set the timeout arbitrarily low so that the query hits the timeout in a
  470. // timely manner.
  471. cluster.Timeout = 1000 * time.Millisecond
  472. cluster.NumConns = 1
  473. db, err := cluster.CreateSession()
  474. if err != nil {
  475. t.Fatalf("NewCluster: %v", err)
  476. }
  477. ch := make(chan error)
  478. go func() {
  479. err := db.Query("timeout").Exec()
  480. ch <- err
  481. }()
  482. // ensure that the above goroutine gets sheduled
  483. time.Sleep(50 * time.Millisecond)
  484. db.Close()
  485. select {
  486. case err = <-ch:
  487. case <-time.After(1 * time.Second):
  488. t.Fatal("timedout waiting to get a response once cluster is closed")
  489. }
  490. if err != ErrConnectionClosed {
  491. t.Fatalf("expected to get %v got %v", ErrConnectionClosed, err)
  492. }
  493. }
  494. func TestStream0(t *testing.T) {
  495. // TODO: replace this with type check
  496. const expErr = "gocql: received unexpected frame on stream 0"
  497. var buf bytes.Buffer
  498. f := newFramer(nil, &buf, nil, protoVersion4)
  499. f.writeHeader(0, opResult, 0)
  500. f.writeInt(resultKindVoid)
  501. f.wbuf[0] |= 0x80
  502. if err := f.finishWrite(); err != nil {
  503. t.Fatal(err)
  504. }
  505. conn := &Conn{
  506. r: bufio.NewReader(&buf),
  507. streams: streams.New(protoVersion4),
  508. }
  509. err := conn.recv()
  510. if err == nil {
  511. t.Fatal("expected to get an error on stream 0")
  512. } else if !strings.HasPrefix(err.Error(), expErr) {
  513. t.Fatalf("expected to get error prefix %q got %q", expErr, err.Error())
  514. }
  515. }
  516. func TestConnClosedBlocked(t *testing.T) {
  517. t.Skip("FLAKE: skipping test flake see https://github.com/gocql/gocql/issues/1088")
  518. // issue 664
  519. const proto = 3
  520. srv := NewTestServer(t, proto, context.Background())
  521. defer srv.Stop()
  522. errorHandler := connErrorHandlerFn(func(conn *Conn, err error, closed bool) {
  523. t.Log(err)
  524. })
  525. s, err := srv.session()
  526. if err != nil {
  527. t.Fatal(err)
  528. }
  529. defer s.Close()
  530. conn, err := s.connect(srv.host(), errorHandler)
  531. if err != nil {
  532. t.Fatal(err)
  533. }
  534. if err := conn.conn.Close(); err != nil {
  535. t.Fatal(err)
  536. }
  537. // This will block indefintaly if #664 is not fixed
  538. err = conn.executeQuery(&Query{stmt: "void"}).Close()
  539. if !strings.HasSuffix(err.Error(), "use of closed network connection") {
  540. t.Fatalf("expected to get use of closed networking connection error got: %v\n", err)
  541. }
  542. }
  543. func TestContext_Timeout(t *testing.T) {
  544. srv := NewTestServer(t, defaultProto, context.Background())
  545. defer srv.Stop()
  546. cluster := testCluster(srv.Address, defaultProto)
  547. cluster.Timeout = 5 * time.Second
  548. db, err := cluster.CreateSession()
  549. if err != nil {
  550. t.Fatal(err)
  551. }
  552. defer db.Close()
  553. ctx, cancel := context.WithCancel(context.Background())
  554. cancel()
  555. err = db.Query("timeout").WithContext(ctx).Exec()
  556. if err != context.Canceled {
  557. t.Fatalf("expected to get context cancel error: %v got %v", context.Canceled, err)
  558. }
  559. }
  560. type recordingFrameHeaderObserver struct {
  561. t *testing.T
  562. mu sync.Mutex
  563. frames []ObservedFrameHeader
  564. }
  565. func (r *recordingFrameHeaderObserver) ObserveFrameHeader(ctx context.Context, frm ObservedFrameHeader) {
  566. r.mu.Lock()
  567. r.frames = append(r.frames, frm)
  568. r.mu.Unlock()
  569. }
  570. func (r *recordingFrameHeaderObserver) getFrames() []ObservedFrameHeader {
  571. r.mu.Lock()
  572. defer r.mu.Unlock()
  573. return r.frames
  574. }
  575. func TestFrameHeaderObserver(t *testing.T) {
  576. srv := NewTestServer(t, defaultProto, context.Background())
  577. defer srv.Stop()
  578. cluster := testCluster(srv.Address, defaultProto)
  579. cluster.NumConns = 1
  580. observer := &recordingFrameHeaderObserver{t: t}
  581. cluster.FrameHeaderObserver = observer
  582. db, err := cluster.CreateSession()
  583. if err != nil {
  584. t.Fatal(err)
  585. }
  586. if err := db.Query("void").Exec(); err != nil {
  587. t.Fatal(err)
  588. }
  589. frames := observer.getFrames()
  590. if len(frames) != 2 {
  591. t.Fatalf("Expected to receive 2 frames, instead received %d", len(frames))
  592. }
  593. readyFrame := frames[0]
  594. if readyFrame.Opcode != frameOp(opReady) {
  595. t.Fatalf("Expected to receive ready frame, instead received frame of opcode %d", readyFrame.Opcode)
  596. }
  597. voidResultFrame := frames[1]
  598. if voidResultFrame.Opcode != frameOp(opResult) {
  599. t.Fatalf("Expected to receive result frame, instead received frame of opcode %d", voidResultFrame.Opcode)
  600. }
  601. if voidResultFrame.Length != int32(4) {
  602. t.Fatalf("Expected to receive frame with body length 4, instead received body length %d", voidResultFrame.Length)
  603. }
  604. }
  605. func NewTestServer(t testing.TB, protocol uint8, ctx context.Context) *TestServer {
  606. laddr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:0")
  607. if err != nil {
  608. t.Fatal(err)
  609. }
  610. listen, err := net.ListenTCP("tcp", laddr)
  611. if err != nil {
  612. t.Fatal(err)
  613. }
  614. headerSize := 8
  615. if protocol > protoVersion2 {
  616. headerSize = 9
  617. }
  618. ctx, cancel := context.WithCancel(ctx)
  619. srv := &TestServer{
  620. Address: listen.Addr().String(),
  621. listen: listen,
  622. t: t,
  623. protocol: protocol,
  624. headerSize: headerSize,
  625. ctx: ctx,
  626. cancel: cancel,
  627. }
  628. go srv.closeWatch()
  629. go srv.serve()
  630. return srv
  631. }
  632. func NewSSLTestServer(t testing.TB, protocol uint8, ctx context.Context) *TestServer {
  633. pem, err := ioutil.ReadFile("testdata/pki/ca.crt")
  634. certPool := x509.NewCertPool()
  635. if !certPool.AppendCertsFromPEM(pem) {
  636. t.Fatalf("Failed parsing or appending certs")
  637. }
  638. mycert, err := tls.LoadX509KeyPair("testdata/pki/cassandra.crt", "testdata/pki/cassandra.key")
  639. if err != nil {
  640. t.Fatalf("could not load cert")
  641. }
  642. config := &tls.Config{
  643. Certificates: []tls.Certificate{mycert},
  644. RootCAs: certPool,
  645. }
  646. listen, err := tls.Listen("tcp", "127.0.0.1:0", config)
  647. if err != nil {
  648. t.Fatal(err)
  649. }
  650. headerSize := 8
  651. if protocol > protoVersion2 {
  652. headerSize = 9
  653. }
  654. ctx, cancel := context.WithCancel(ctx)
  655. srv := &TestServer{
  656. Address: listen.Addr().String(),
  657. listen: listen,
  658. t: t,
  659. protocol: protocol,
  660. headerSize: headerSize,
  661. ctx: ctx,
  662. cancel: cancel,
  663. }
  664. go srv.closeWatch()
  665. go srv.serve()
  666. return srv
  667. }
  668. type TestServer struct {
  669. Address string
  670. TimeoutOnStartup int32
  671. t testing.TB
  672. nreq uint64
  673. listen net.Listener
  674. nKillReq int64
  675. nQueries uint64
  676. compressor Compressor
  677. protocol byte
  678. headerSize int
  679. ctx context.Context
  680. cancel context.CancelFunc
  681. quit chan struct{}
  682. mu sync.Mutex
  683. closed bool
  684. }
  685. func (srv *TestServer) session() (*Session, error) {
  686. return testCluster(srv.Address, protoVersion(srv.protocol)).CreateSession()
  687. }
  688. func (srv *TestServer) host() *HostInfo {
  689. hosts, err := hostInfo(srv.Address, 9042)
  690. if err != nil {
  691. srv.t.Fatal(err)
  692. }
  693. return hosts[0]
  694. }
  695. func (srv *TestServer) closeWatch() {
  696. <-srv.ctx.Done()
  697. srv.mu.Lock()
  698. defer srv.mu.Unlock()
  699. srv.closeLocked()
  700. }
  701. func (srv *TestServer) serve() {
  702. defer srv.listen.Close()
  703. for !srv.isClosed() {
  704. conn, err := srv.listen.Accept()
  705. if err != nil {
  706. break
  707. }
  708. go func(conn net.Conn) {
  709. defer conn.Close()
  710. for !srv.isClosed() {
  711. framer, err := srv.readFrame(conn)
  712. if err != nil {
  713. if err == io.EOF {
  714. return
  715. }
  716. srv.errorLocked(err)
  717. return
  718. }
  719. atomic.AddUint64(&srv.nreq, 1)
  720. go srv.process(framer)
  721. }
  722. }(conn)
  723. }
  724. }
  725. func (srv *TestServer) isClosed() bool {
  726. srv.mu.Lock()
  727. defer srv.mu.Unlock()
  728. return srv.closed
  729. }
  730. func (srv *TestServer) closeLocked() {
  731. if srv.closed {
  732. return
  733. }
  734. srv.closed = true
  735. srv.listen.Close()
  736. srv.cancel()
  737. }
  738. func (srv *TestServer) Stop() {
  739. srv.mu.Lock()
  740. defer srv.mu.Unlock()
  741. srv.closeLocked()
  742. }
  743. func (srv *TestServer) errorLocked(err interface{}) {
  744. srv.mu.Lock()
  745. defer srv.mu.Unlock()
  746. if srv.closed {
  747. return
  748. }
  749. srv.t.Error(err)
  750. }
  751. func (srv *TestServer) process(f *framer) {
  752. head := f.header
  753. if head == nil {
  754. srv.errorLocked("process frame with a nil header")
  755. return
  756. }
  757. switch head.op {
  758. case opStartup:
  759. if atomic.LoadInt32(&srv.TimeoutOnStartup) > 0 {
  760. // Do not respond to startup command
  761. // wait until we get a cancel signal
  762. select {
  763. case <-srv.ctx.Done():
  764. return
  765. }
  766. }
  767. f.writeHeader(0, opReady, head.stream)
  768. case opOptions:
  769. f.writeHeader(0, opSupported, head.stream)
  770. f.writeShort(0)
  771. case opQuery:
  772. atomic.AddUint64(&srv.nQueries, 1)
  773. query := f.readLongString()
  774. first := query
  775. if n := strings.Index(query, " "); n > 0 {
  776. first = first[:n]
  777. }
  778. switch strings.ToLower(first) {
  779. case "kill":
  780. atomic.AddInt64(&srv.nKillReq, 1)
  781. f.writeHeader(0, opError, head.stream)
  782. f.writeInt(0x1001)
  783. f.writeString("query killed")
  784. case "use":
  785. f.writeInt(resultKindKeyspace)
  786. f.writeString(strings.TrimSpace(query[3:]))
  787. case "void":
  788. f.writeHeader(0, opResult, head.stream)
  789. f.writeInt(resultKindVoid)
  790. case "timeout":
  791. <-srv.ctx.Done()
  792. return
  793. case "slow":
  794. go func() {
  795. f.writeHeader(0, opResult, head.stream)
  796. f.writeInt(resultKindVoid)
  797. f.wbuf[0] = srv.protocol | 0x80
  798. select {
  799. case <-srv.ctx.Done():
  800. return
  801. case <-time.After(50 * time.Millisecond):
  802. f.finishWrite()
  803. }
  804. }()
  805. return
  806. default:
  807. f.writeHeader(0, opResult, head.stream)
  808. f.writeInt(resultKindVoid)
  809. }
  810. case opError:
  811. f.writeHeader(0, opError, head.stream)
  812. f.wbuf = append(f.wbuf, f.rbuf...)
  813. default:
  814. f.writeHeader(0, opError, head.stream)
  815. f.writeInt(0)
  816. f.writeString("not supported")
  817. }
  818. f.wbuf[0] = srv.protocol | 0x80
  819. if err := f.finishWrite(); err != nil {
  820. srv.errorLocked(err)
  821. }
  822. }
  823. func (srv *TestServer) readFrame(conn net.Conn) (*framer, error) {
  824. buf := make([]byte, srv.headerSize)
  825. head, err := readHeader(conn, buf)
  826. if err != nil {
  827. return nil, err
  828. }
  829. framer := newFramer(conn, conn, nil, srv.protocol)
  830. err = framer.readFrame(&head)
  831. if err != nil {
  832. return nil, err
  833. }
  834. // should be a request frame
  835. if head.version.response() {
  836. return nil, fmt.Errorf("expected to read a request frame got version: %v", head.version)
  837. } else if head.version.version() != srv.protocol {
  838. return nil, fmt.Errorf("expected to read protocol version 0x%x got 0x%x", srv.protocol, head.version.version())
  839. }
  840. return framer, nil
  841. }