github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/state/session_test.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "reflect" 6 "strings" 7 "testing" 8 "time" 9 10 "github.com/hashicorp/consul/agent/structs" 11 "github.com/hashicorp/consul/api" 12 "github.com/hashicorp/consul/types" 13 "github.com/hashicorp/go-memdb" 14 ) 15 16 func TestStateStore_SessionCreate_SessionGet(t *testing.T) { 17 s := testStateStore(t) 18 19 // SessionGet returns nil if the session doesn't exist 20 ws := memdb.NewWatchSet() 21 idx, session, err := s.SessionGet(ws, testUUID()) 22 if session != nil || err != nil { 23 t.Fatalf("expected (nil, nil), got: (%#v, %#v)", session, err) 24 } 25 if idx != 0 { 26 t.Fatalf("bad index: %d", idx) 27 } 28 29 // Registering without a session ID is disallowed 30 err = s.SessionCreate(1, &structs.Session{}) 31 if err != ErrMissingSessionID { 32 t.Fatalf("expected %#v, got: %#v", ErrMissingSessionID, err) 33 } 34 35 // Invalid session behavior throws error 36 sess := &structs.Session{ 37 ID: testUUID(), 38 Behavior: "nope", 39 } 40 err = s.SessionCreate(1, sess) 41 if err == nil || !strings.Contains(err.Error(), "session behavior") { 42 t.Fatalf("expected session behavior error, got: %#v", err) 43 } 44 45 // Registering with an unknown node is disallowed 46 sess = &structs.Session{ID: testUUID()} 47 if err := s.SessionCreate(1, sess); err != ErrMissingNode { 48 t.Fatalf("expected %#v, got: %#v", ErrMissingNode, err) 49 } 50 51 // None of the errored operations modified the index 52 if idx := s.maxIndex("sessions"); idx != 0 { 53 t.Fatalf("bad index: %d", idx) 54 } 55 if watchFired(ws) { 56 t.Fatalf("bad") 57 } 58 59 // Valid session is able to register 60 testRegisterNode(t, s, 1, "node1") 61 sess = &structs.Session{ 62 ID: testUUID(), 63 Node: "node1", 64 } 65 if err := s.SessionCreate(2, sess); err != nil { 66 t.Fatalf("err: %s", err) 67 } 68 if idx := s.maxIndex("sessions"); idx != 2 { 69 t.Fatalf("bad index: %s", err) 70 } 71 if !watchFired(ws) { 72 t.Fatalf("bad") 73 } 74 75 // Retrieve the session again 76 ws = memdb.NewWatchSet() 77 idx, session, err = s.SessionGet(ws, sess.ID) 78 if err != nil { 79 t.Fatalf("err: %s", err) 80 } 81 if idx != 2 { 82 t.Fatalf("bad index: %d", idx) 83 } 84 85 // Ensure the session looks correct and was assigned the 86 // proper default value for session behavior. 87 expect := &structs.Session{ 88 ID: sess.ID, 89 Behavior: structs.SessionKeysRelease, 90 Node: "node1", 91 RaftIndex: structs.RaftIndex{ 92 CreateIndex: 2, 93 ModifyIndex: 2, 94 }, 95 } 96 if !reflect.DeepEqual(expect, session) { 97 t.Fatalf("bad session: %#v", session) 98 } 99 100 // Registering with a non-existent check is disallowed 101 sess = &structs.Session{ 102 ID: testUUID(), 103 Node: "node1", 104 Checks: []types.CheckID{"check1"}, 105 } 106 err = s.SessionCreate(3, sess) 107 if err == nil || !strings.Contains(err.Error(), "Missing check") { 108 t.Fatalf("expected missing check error, got: %#v", err) 109 } 110 111 // Registering with a critical check is disallowed 112 testRegisterCheck(t, s, 3, "node1", "", "check1", api.HealthCritical) 113 err = s.SessionCreate(4, sess) 114 if err == nil || !strings.Contains(err.Error(), api.HealthCritical) { 115 t.Fatalf("expected critical state error, got: %#v", err) 116 } 117 if watchFired(ws) { 118 t.Fatalf("bad") 119 } 120 121 // Registering with a healthy check succeeds (doesn't hit the watch since 122 // we are looking at the old session). 123 testRegisterCheck(t, s, 4, "node1", "", "check1", api.HealthPassing) 124 if err := s.SessionCreate(5, sess); err != nil { 125 t.Fatalf("err: %s", err) 126 } 127 if watchFired(ws) { 128 t.Fatalf("bad") 129 } 130 131 // Register a session against two checks. 132 testRegisterCheck(t, s, 5, "node1", "", "check2", api.HealthPassing) 133 sess2 := &structs.Session{ 134 ID: testUUID(), 135 Node: "node1", 136 Checks: []types.CheckID{"check1", "check2"}, 137 } 138 if err := s.SessionCreate(6, sess2); err != nil { 139 t.Fatalf("err: %s", err) 140 } 141 142 tx := s.db.Txn(false) 143 defer tx.Abort() 144 145 // Check mappings were inserted 146 { 147 check, err := tx.First("session_checks", "session", sess.ID) 148 if err != nil { 149 t.Fatalf("err: %s", err) 150 } 151 if check == nil { 152 t.Fatalf("missing session check") 153 } 154 expectCheck := &sessionCheck{ 155 Node: "node1", 156 CheckID: "check1", 157 Session: sess.ID, 158 } 159 if actual := check.(*sessionCheck); !reflect.DeepEqual(actual, expectCheck) { 160 t.Fatalf("expected %#v, got: %#v", expectCheck, actual) 161 } 162 } 163 checks, err := tx.Get("session_checks", "session", sess2.ID) 164 if err != nil { 165 t.Fatalf("err: %s", err) 166 } 167 for i, check := 0, checks.Next(); check != nil; i, check = i+1, checks.Next() { 168 expectCheck := &sessionCheck{ 169 Node: "node1", 170 CheckID: types.CheckID(fmt.Sprintf("check%d", i+1)), 171 Session: sess2.ID, 172 } 173 if actual := check.(*sessionCheck); !reflect.DeepEqual(actual, expectCheck) { 174 t.Fatalf("expected %#v, got: %#v", expectCheck, actual) 175 } 176 } 177 178 // Pulling a nonexistent session gives the table index. 179 idx, session, err = s.SessionGet(nil, testUUID()) 180 if err != nil { 181 t.Fatalf("err: %s", err) 182 } 183 if session != nil { 184 t.Fatalf("expected not to get a session: %v", session) 185 } 186 if idx != 6 { 187 t.Fatalf("bad index: %d", idx) 188 } 189 } 190 191 func TegstStateStore_SessionList(t *testing.T) { 192 s := testStateStore(t) 193 194 // Listing when no sessions exist returns nil 195 ws := memdb.NewWatchSet() 196 idx, res, err := s.SessionList(ws) 197 if idx != 0 || res != nil || err != nil { 198 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 199 } 200 201 // Register some nodes 202 testRegisterNode(t, s, 1, "node1") 203 testRegisterNode(t, s, 2, "node2") 204 testRegisterNode(t, s, 3, "node3") 205 206 // Create some sessions in the state store 207 sessions := structs.Sessions{ 208 &structs.Session{ 209 ID: testUUID(), 210 Node: "node1", 211 Behavior: structs.SessionKeysDelete, 212 }, 213 &structs.Session{ 214 ID: testUUID(), 215 Node: "node2", 216 Behavior: structs.SessionKeysRelease, 217 }, 218 &structs.Session{ 219 ID: testUUID(), 220 Node: "node3", 221 Behavior: structs.SessionKeysDelete, 222 }, 223 } 224 for i, session := range sessions { 225 if err := s.SessionCreate(uint64(4+i), session); err != nil { 226 t.Fatalf("err: %s", err) 227 } 228 } 229 if !watchFired(ws) { 230 t.Fatalf("bad") 231 } 232 233 // List out all of the sessions 234 idx, sessionList, err := s.SessionList(nil) 235 if err != nil { 236 t.Fatalf("err: %s", err) 237 } 238 if idx != 6 { 239 t.Fatalf("bad index: %d", idx) 240 } 241 if !reflect.DeepEqual(sessionList, sessions) { 242 t.Fatalf("bad: %#v", sessions) 243 } 244 } 245 246 func TestStateStore_NodeSessions(t *testing.T) { 247 s := testStateStore(t) 248 249 // Listing sessions with no results returns nil 250 ws := memdb.NewWatchSet() 251 idx, res, err := s.NodeSessions(ws, "node1") 252 if idx != 0 || res != nil || err != nil { 253 t.Fatalf("expected (0, nil, nil), got: (%d, %#v, %#v)", idx, res, err) 254 } 255 256 // Create the nodes 257 testRegisterNode(t, s, 1, "node1") 258 testRegisterNode(t, s, 2, "node2") 259 260 // Register some sessions with the nodes 261 sessions1 := structs.Sessions{ 262 &structs.Session{ 263 ID: testUUID(), 264 Node: "node1", 265 }, 266 &structs.Session{ 267 ID: testUUID(), 268 Node: "node1", 269 }, 270 } 271 sessions2 := []*structs.Session{ 272 &structs.Session{ 273 ID: testUUID(), 274 Node: "node2", 275 }, 276 &structs.Session{ 277 ID: testUUID(), 278 Node: "node2", 279 }, 280 } 281 for i, sess := range append(sessions1, sessions2...) { 282 if err := s.SessionCreate(uint64(3+i), sess); err != nil { 283 t.Fatalf("err: %s", err) 284 } 285 } 286 if !watchFired(ws) { 287 t.Fatalf("bad") 288 } 289 290 // Query all of the sessions associated with a specific 291 // node in the state store. 292 ws1 := memdb.NewWatchSet() 293 idx, res, err = s.NodeSessions(ws1, "node1") 294 if err != nil { 295 t.Fatalf("err: %s", err) 296 } 297 if len(res) != len(sessions1) { 298 t.Fatalf("bad: %#v", res) 299 } 300 if idx != 6 { 301 t.Fatalf("bad index: %d", idx) 302 } 303 304 ws2 := memdb.NewWatchSet() 305 idx, res, err = s.NodeSessions(ws2, "node2") 306 if err != nil { 307 t.Fatalf("err: %s", err) 308 } 309 if len(res) != len(sessions2) { 310 t.Fatalf("bad: %#v", res) 311 } 312 if idx != 6 { 313 t.Fatalf("bad index: %d", idx) 314 } 315 316 // Destroying a session on node1 should not affect node2's watch. 317 if err := s.SessionDestroy(100, sessions1[0].ID); err != nil { 318 t.Fatalf("err: %s", err) 319 } 320 if !watchFired(ws1) { 321 t.Fatalf("bad") 322 } 323 if watchFired(ws2) { 324 t.Fatalf("bad") 325 } 326 } 327 328 func TestStateStore_SessionDestroy(t *testing.T) { 329 s := testStateStore(t) 330 331 // Session destroy is idempotent and returns no error 332 // if the session doesn't exist. 333 if err := s.SessionDestroy(1, testUUID()); err != nil { 334 t.Fatalf("err: %s", err) 335 } 336 337 // Ensure the index was not updated if nothing was destroyed. 338 if idx := s.maxIndex("sessions"); idx != 0 { 339 t.Fatalf("bad index: %d", idx) 340 } 341 342 // Register a node. 343 testRegisterNode(t, s, 1, "node1") 344 345 // Register a new session 346 sess := &structs.Session{ 347 ID: testUUID(), 348 Node: "node1", 349 } 350 if err := s.SessionCreate(2, sess); err != nil { 351 t.Fatalf("err: %s", err) 352 } 353 354 // Destroy the session. 355 if err := s.SessionDestroy(3, sess.ID); err != nil { 356 t.Fatalf("err: %s", err) 357 } 358 359 // Check that the index was updated 360 if idx := s.maxIndex("sessions"); idx != 3 { 361 t.Fatalf("bad index: %d", idx) 362 } 363 364 // Make sure the session is really gone. 365 tx := s.db.Txn(false) 366 sessions, err := tx.Get("sessions", "id") 367 if err != nil || sessions.Next() != nil { 368 t.Fatalf("session should not exist") 369 } 370 tx.Abort() 371 } 372 373 func TestStateStore_Session_Snapshot_Restore(t *testing.T) { 374 s := testStateStore(t) 375 376 // Register some nodes and checks. 377 testRegisterNode(t, s, 1, "node1") 378 testRegisterNode(t, s, 2, "node2") 379 testRegisterNode(t, s, 3, "node3") 380 testRegisterCheck(t, s, 4, "node1", "", "check1", api.HealthPassing) 381 382 // Create some sessions in the state store. 383 session1 := testUUID() 384 sessions := structs.Sessions{ 385 &structs.Session{ 386 ID: session1, 387 Node: "node1", 388 Behavior: structs.SessionKeysDelete, 389 Checks: []types.CheckID{"check1"}, 390 }, 391 &structs.Session{ 392 ID: testUUID(), 393 Node: "node2", 394 Behavior: structs.SessionKeysRelease, 395 LockDelay: 10 * time.Second, 396 }, 397 &structs.Session{ 398 ID: testUUID(), 399 Node: "node3", 400 Behavior: structs.SessionKeysDelete, 401 TTL: "1.5s", 402 }, 403 } 404 for i, session := range sessions { 405 if err := s.SessionCreate(uint64(5+i), session); err != nil { 406 t.Fatalf("err: %s", err) 407 } 408 } 409 410 // Snapshot the sessions. 411 snap := s.Snapshot() 412 defer snap.Close() 413 414 // Alter the real state store. 415 if err := s.SessionDestroy(8, session1); err != nil { 416 t.Fatalf("err: %s", err) 417 } 418 419 // Verify the snapshot. 420 if idx := snap.LastIndex(); idx != 7 { 421 t.Fatalf("bad index: %d", idx) 422 } 423 iter, err := snap.Sessions() 424 if err != nil { 425 t.Fatalf("err: %s", err) 426 } 427 var dump structs.Sessions 428 for session := iter.Next(); session != nil; session = iter.Next() { 429 sess := session.(*structs.Session) 430 dump = append(dump, sess) 431 432 found := false 433 for i := range sessions { 434 if sess.ID == sessions[i].ID { 435 if !reflect.DeepEqual(sess, sessions[i]) { 436 t.Fatalf("bad: %#v", sess) 437 } 438 found = true 439 } 440 } 441 if !found { 442 t.Fatalf("bad: %#v", sess) 443 } 444 } 445 446 // Restore the sessions into a new state store. 447 func() { 448 s := testStateStore(t) 449 restore := s.Restore() 450 for _, session := range dump { 451 if err := restore.Session(session); err != nil { 452 t.Fatalf("err: %s", err) 453 } 454 } 455 restore.Commit() 456 457 // Read the restored sessions back out and verify that they 458 // match. 459 idx, res, err := s.SessionList(nil) 460 if err != nil { 461 t.Fatalf("err: %s", err) 462 } 463 if idx != 7 { 464 t.Fatalf("bad index: %d", idx) 465 } 466 for _, sess := range res { 467 found := false 468 for i := range sessions { 469 if sess.ID == sessions[i].ID { 470 if !reflect.DeepEqual(sess, sessions[i]) { 471 t.Fatalf("bad: %#v", sess) 472 } 473 found = true 474 } 475 } 476 if !found { 477 t.Fatalf("bad: %#v", sess) 478 } 479 } 480 481 // Check that the index was updated. 482 if idx := s.maxIndex("sessions"); idx != 7 { 483 t.Fatalf("bad index: %d", idx) 484 } 485 486 // Manually verify that the session check mapping got restored. 487 tx := s.db.Txn(false) 488 defer tx.Abort() 489 490 check, err := tx.First("session_checks", "session", session1) 491 if err != nil { 492 t.Fatalf("err: %s", err) 493 } 494 if check == nil { 495 t.Fatalf("missing session check") 496 } 497 expectCheck := &sessionCheck{ 498 Node: "node1", 499 CheckID: "check1", 500 Session: session1, 501 } 502 if actual := check.(*sessionCheck); !reflect.DeepEqual(actual, expectCheck) { 503 t.Fatalf("expected %#v, got: %#v", expectCheck, actual) 504 } 505 }() 506 } 507 508 func TestStateStore_Session_Invalidate_DeleteNode(t *testing.T) { 509 s := testStateStore(t) 510 511 // Set up our test environment. 512 if err := s.EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 513 t.Fatalf("err: %v", err) 514 } 515 session := &structs.Session{ 516 ID: testUUID(), 517 Node: "foo", 518 } 519 if err := s.SessionCreate(14, session); err != nil { 520 t.Fatalf("err: %v", err) 521 } 522 523 // Delete the node and make sure the watch fires. 524 ws := memdb.NewWatchSet() 525 idx, s2, err := s.SessionGet(ws, session.ID) 526 if err != nil { 527 t.Fatalf("err: %v", err) 528 } 529 if err := s.DeleteNode(15, "foo"); err != nil { 530 t.Fatalf("err: %v", err) 531 } 532 if !watchFired(ws) { 533 t.Fatalf("bad") 534 } 535 536 // Lookup by ID, should be nil. 537 idx, s2, err = s.SessionGet(nil, session.ID) 538 if err != nil { 539 t.Fatalf("err: %v", err) 540 } 541 if s2 != nil { 542 t.Fatalf("session should be invalidated") 543 } 544 if idx != 15 { 545 t.Fatalf("bad index: %d", idx) 546 } 547 } 548 549 func TestStateStore_Session_Invalidate_DeleteService(t *testing.T) { 550 s := testStateStore(t) 551 552 // Set up our test environment. 553 if err := s.EnsureNode(11, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 554 t.Fatalf("err: %v", err) 555 } 556 if err := s.EnsureService(12, "foo", &structs.NodeService{ID: "api", Service: "api", Tags: nil, Address: "", Port: 5000}); err != nil { 557 t.Fatalf("err: %v", err) 558 } 559 check := &structs.HealthCheck{ 560 Node: "foo", 561 CheckID: "api", 562 Name: "Can connect", 563 Status: api.HealthPassing, 564 ServiceID: "api", 565 } 566 if err := s.EnsureCheck(13, check); err != nil { 567 t.Fatalf("err: %v", err) 568 } 569 session := &structs.Session{ 570 ID: testUUID(), 571 Node: "foo", 572 Checks: []types.CheckID{"api"}, 573 } 574 if err := s.SessionCreate(14, session); err != nil { 575 t.Fatalf("err: %v", err) 576 } 577 578 // Delete the service and make sure the watch fires. 579 ws := memdb.NewWatchSet() 580 idx, s2, err := s.SessionGet(ws, session.ID) 581 if err != nil { 582 t.Fatalf("err: %v", err) 583 } 584 if err := s.DeleteService(15, "foo", "api"); err != nil { 585 t.Fatalf("err: %v", err) 586 } 587 if !watchFired(ws) { 588 t.Fatalf("bad") 589 } 590 591 // Lookup by ID, should be nil. 592 idx, s2, err = s.SessionGet(nil, session.ID) 593 if err != nil { 594 t.Fatalf("err: %v", err) 595 } 596 if s2 != nil { 597 t.Fatalf("session should be invalidated") 598 } 599 if idx != 15 { 600 t.Fatalf("bad index: %d", idx) 601 } 602 } 603 604 func TestStateStore_Session_Invalidate_Critical_Check(t *testing.T) { 605 s := testStateStore(t) 606 607 // Set up our test environment. 608 if err := s.EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 609 t.Fatalf("err: %v", err) 610 } 611 check := &structs.HealthCheck{ 612 Node: "foo", 613 CheckID: "bar", 614 Status: api.HealthPassing, 615 } 616 if err := s.EnsureCheck(13, check); err != nil { 617 t.Fatalf("err: %v", err) 618 } 619 session := &structs.Session{ 620 ID: testUUID(), 621 Node: "foo", 622 Checks: []types.CheckID{"bar"}, 623 } 624 if err := s.SessionCreate(14, session); err != nil { 625 t.Fatalf("err: %v", err) 626 } 627 628 // Invalidate the check and make sure the watches fire. 629 ws := memdb.NewWatchSet() 630 idx, s2, err := s.SessionGet(ws, session.ID) 631 if err != nil { 632 t.Fatalf("err: %v", err) 633 } 634 check.Status = api.HealthCritical 635 if err := s.EnsureCheck(15, check); err != nil { 636 t.Fatalf("err: %v", err) 637 } 638 if !watchFired(ws) { 639 t.Fatalf("bad") 640 } 641 642 // Lookup by ID, should be nil. 643 idx, s2, err = s.SessionGet(nil, session.ID) 644 if err != nil { 645 t.Fatalf("err: %v", err) 646 } 647 if s2 != nil { 648 t.Fatalf("session should be invalidated") 649 } 650 if idx != 15 { 651 t.Fatalf("bad index: %d", idx) 652 } 653 } 654 655 func TestStateStore_Session_Invalidate_DeleteCheck(t *testing.T) { 656 s := testStateStore(t) 657 658 // Set up our test environment. 659 if err := s.EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 660 t.Fatalf("err: %v", err) 661 } 662 check := &structs.HealthCheck{ 663 Node: "foo", 664 CheckID: "bar", 665 Status: api.HealthPassing, 666 } 667 if err := s.EnsureCheck(13, check); err != nil { 668 t.Fatalf("err: %v", err) 669 } 670 session := &structs.Session{ 671 ID: testUUID(), 672 Node: "foo", 673 Checks: []types.CheckID{"bar"}, 674 } 675 if err := s.SessionCreate(14, session); err != nil { 676 t.Fatalf("err: %v", err) 677 } 678 679 // Delete the check and make sure the watches fire. 680 ws := memdb.NewWatchSet() 681 idx, s2, err := s.SessionGet(ws, session.ID) 682 if err != nil { 683 t.Fatalf("err: %v", err) 684 } 685 if err := s.DeleteCheck(15, "foo", "bar"); err != nil { 686 t.Fatalf("err: %v", err) 687 } 688 if !watchFired(ws) { 689 t.Fatalf("bad") 690 } 691 692 // Lookup by ID, should be nil. 693 idx, s2, err = s.SessionGet(nil, session.ID) 694 if err != nil { 695 t.Fatalf("err: %v", err) 696 } 697 if s2 != nil { 698 t.Fatalf("session should be invalidated") 699 } 700 if idx != 15 { 701 t.Fatalf("bad index: %d", idx) 702 } 703 704 // Manually make sure the session checks mapping is clear. 705 tx := s.db.Txn(false) 706 mapping, err := tx.First("session_checks", "session", session.ID) 707 if err != nil { 708 t.Fatalf("err: %s", err) 709 } 710 if mapping != nil { 711 t.Fatalf("unexpected session check") 712 } 713 tx.Abort() 714 } 715 716 func TestStateStore_Session_Invalidate_Key_Unlock_Behavior(t *testing.T) { 717 s := testStateStore(t) 718 719 // Set up our test environment. 720 if err := s.EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 721 t.Fatalf("err: %v", err) 722 } 723 session := &structs.Session{ 724 ID: testUUID(), 725 Node: "foo", 726 LockDelay: 50 * time.Millisecond, 727 } 728 if err := s.SessionCreate(4, session); err != nil { 729 t.Fatalf("err: %v", err) 730 } 731 732 // Lock a key with the session. 733 d := &structs.DirEntry{ 734 Key: "/foo", 735 Flags: 42, 736 Value: []byte("test"), 737 Session: session.ID, 738 } 739 ok, err := s.KVSLock(5, d) 740 if err != nil { 741 t.Fatalf("err: %v", err) 742 } 743 if !ok { 744 t.Fatalf("unexpected fail") 745 } 746 747 // Delete the node and make sure the watches fire. 748 ws := memdb.NewWatchSet() 749 idx, s2, err := s.SessionGet(ws, session.ID) 750 if err != nil { 751 t.Fatalf("err: %v", err) 752 } 753 if err := s.DeleteNode(6, "foo"); err != nil { 754 t.Fatalf("err: %v", err) 755 } 756 if !watchFired(ws) { 757 t.Fatalf("bad") 758 } 759 760 // Lookup by ID, should be nil. 761 idx, s2, err = s.SessionGet(nil, session.ID) 762 if err != nil { 763 t.Fatalf("err: %v", err) 764 } 765 if s2 != nil { 766 t.Fatalf("session should be invalidated") 767 } 768 if idx != 6 { 769 t.Fatalf("bad index: %d", idx) 770 } 771 772 // Key should be unlocked. 773 idx, d2, err := s.KVSGet(nil, "/foo") 774 if err != nil { 775 t.Fatalf("err: %s", err) 776 } 777 if d2.ModifyIndex != 6 { 778 t.Fatalf("bad index: %v", d2.ModifyIndex) 779 } 780 if d2.LockIndex != 1 { 781 t.Fatalf("bad: %v", *d2) 782 } 783 if d2.Session != "" { 784 t.Fatalf("bad: %v", *d2) 785 } 786 if idx != 6 { 787 t.Fatalf("bad index: %d", idx) 788 } 789 790 // Key should have a lock delay. 791 expires := s.KVSLockDelay("/foo") 792 if expires.Before(time.Now().Add(30 * time.Millisecond)) { 793 t.Fatalf("Bad: %v", expires) 794 } 795 } 796 797 func TestStateStore_Session_Invalidate_Key_Delete_Behavior(t *testing.T) { 798 s := testStateStore(t) 799 800 // Set up our test environment. 801 if err := s.EnsureNode(3, &structs.Node{Node: "foo", Address: "127.0.0.1"}); err != nil { 802 t.Fatalf("err: %v", err) 803 } 804 session := &structs.Session{ 805 ID: testUUID(), 806 Node: "foo", 807 LockDelay: 50 * time.Millisecond, 808 Behavior: structs.SessionKeysDelete, 809 } 810 if err := s.SessionCreate(4, session); err != nil { 811 t.Fatalf("err: %v", err) 812 } 813 814 // Lock a key with the session. 815 d := &structs.DirEntry{ 816 Key: "/bar", 817 Flags: 42, 818 Value: []byte("test"), 819 Session: session.ID, 820 } 821 ok, err := s.KVSLock(5, d) 822 if err != nil { 823 t.Fatalf("err: %v", err) 824 } 825 if !ok { 826 t.Fatalf("unexpected fail") 827 } 828 829 // Delete the node and make sure the watches fire. 830 ws := memdb.NewWatchSet() 831 idx, s2, err := s.SessionGet(ws, session.ID) 832 if err != nil { 833 t.Fatalf("err: %v", err) 834 } 835 if err := s.DeleteNode(6, "foo"); err != nil { 836 t.Fatalf("err: %v", err) 837 } 838 if !watchFired(ws) { 839 t.Fatalf("bad") 840 } 841 842 // Lookup by ID, should be nil. 843 idx, s2, err = s.SessionGet(nil, session.ID) 844 if err != nil { 845 t.Fatalf("err: %v", err) 846 } 847 if s2 != nil { 848 t.Fatalf("session should be invalidated") 849 } 850 if idx != 6 { 851 t.Fatalf("bad index: %d", idx) 852 } 853 854 // Key should be deleted. 855 idx, d2, err := s.KVSGet(nil, "/bar") 856 if err != nil { 857 t.Fatalf("err: %s", err) 858 } 859 if d2 != nil { 860 t.Fatalf("unexpected deleted key") 861 } 862 if idx != 6 { 863 t.Fatalf("bad index: %d", idx) 864 } 865 866 // Key should have a lock delay. 867 expires := s.KVSLockDelay("/bar") 868 if expires.Before(time.Now().Add(30 * time.Millisecond)) { 869 t.Fatalf("Bad: %v", expires) 870 } 871 } 872 873 func TestStateStore_Session_Invalidate_PreparedQuery_Delete(t *testing.T) { 874 s := testStateStore(t) 875 876 // Set up our test environment. 877 testRegisterNode(t, s, 1, "foo") 878 testRegisterService(t, s, 2, "foo", "redis") 879 session := &structs.Session{ 880 ID: testUUID(), 881 Node: "foo", 882 } 883 if err := s.SessionCreate(3, session); err != nil { 884 t.Fatalf("err: %v", err) 885 } 886 query := &structs.PreparedQuery{ 887 ID: testUUID(), 888 Session: session.ID, 889 Service: structs.ServiceQuery{ 890 Service: "redis", 891 }, 892 } 893 if err := s.PreparedQuerySet(4, query); err != nil { 894 t.Fatalf("err: %s", err) 895 } 896 897 // Invalidate the session and make sure the watches fire. 898 ws := memdb.NewWatchSet() 899 idx, s2, err := s.SessionGet(ws, session.ID) 900 if err != nil { 901 t.Fatalf("err: %v", err) 902 } 903 if err := s.SessionDestroy(5, session.ID); err != nil { 904 t.Fatalf("err: %v", err) 905 } 906 if !watchFired(ws) { 907 t.Fatalf("bad") 908 } 909 910 // Make sure the session is gone. 911 idx, s2, err = s.SessionGet(nil, session.ID) 912 if err != nil { 913 t.Fatalf("err: %v", err) 914 } 915 if s2 != nil { 916 t.Fatalf("session should be invalidated") 917 } 918 if idx != 5 { 919 t.Fatalf("bad index: %d", idx) 920 } 921 922 // Make sure the query is gone and the index is updated. 923 idx, q2, err := s.PreparedQueryGet(nil, query.ID) 924 if err != nil { 925 t.Fatalf("err: %s", err) 926 } 927 if idx != 5 { 928 t.Fatalf("bad index: %d", idx) 929 } 930 if q2 != nil { 931 t.Fatalf("bad: %v", q2) 932 } 933 }