/test/test_mem_cache.rb
Ruby | 744 lines | 688 code | 56 blank | 0 comment | 1 complexity | c5cf0b53ba8f9e035cc6a8a6b4c21a5f MD5 | raw file
1require 'stringio' 2require 'test/unit' 3require 'rubygems' 4require 'test/zentest_assertions' 5 6$TESTING = true 7 8require 'memcache' 9 10class MemCache 11 12 attr_writer :namespace 13 14end 15 16class FakeSocket 17 18 attr_reader :written, :data 19 20 def initialize 21 @written = StringIO.new 22 @data = StringIO.new 23 end 24 25 def write(data) 26 @written.write data 27 end 28 29 def gets 30 @data.gets 31 end 32 33 def read(arg) 34 @data.read arg 35 end 36 37end 38 39class FakeServer 40 41 attr_reader :host, :port, :socket 42 43 def initialize(socket = nil) 44 @closed = false 45 @host = 'example.com' 46 @port = 11211 47 @socket = socket || FakeSocket.new 48 end 49 50 def close 51 @closed = true 52 end 53 54 def alive? 55 !@closed 56 end 57 58end 59 60class TestMemCache < Test::Unit::TestCase 61 62 def setup 63 @cache = MemCache.new 'localhost:1', :namespace => 'my_namespace' 64 end 65 66 def test_cache_get 67 server = util_setup_fake_server 68 69 assert_equal "\004\b\"\0170123456789", 70 @cache.cache_get(server, 'my_namespace:key') 71 72 assert_equal "get my_namespace:key\r\n", 73 server.socket.written.string 74 end 75 76 def test_cache_get_EOF 77 server = util_setup_fake_server 78 server.socket.data.string = '' 79 80 e = assert_raise MemCache::MemCacheError do 81 @cache.cache_get server, 'my_namespace:key' 82 end 83 84 assert_equal "lost connection to example.com:11211", e.message 85 end 86 87 def test_cache_get_bad_state 88 server = FakeServer.new 89 server.socket.data.write "bogus response\r\n" 90 server.socket.data.rewind 91 92 @cache.servers = [] 93 @cache.servers << server 94 95 e = assert_raise MemCache::MemCacheError do 96 @cache.cache_get(server, 'my_namespace:key') 97 end 98 99 assert_equal "unexpected response \"bogus response\\r\\n\"", e.message 100 101 deny server.alive? 102 103 assert_equal "get my_namespace:key\r\n", 104 server.socket.written.string 105 end 106 107 def test_cache_get_miss 108 socket = FakeSocket.new 109 socket.data.write "END\r\n" 110 socket.data.rewind 111 server = FakeServer.new socket 112 113 assert_equal nil, @cache.cache_get(server, 'my_namespace:key') 114 115 assert_equal "get my_namespace:key\r\n", 116 socket.written.string 117 end 118 119 def test_cache_get_multi 120 server = util_setup_fake_server 121 server.socket.data.write "VALUE foo 0 7\r\n" 122 server.socket.data.write "\004\b\"\bfoo\r\n" 123 server.socket.data.write "VALUE bar 0 7\r\n" 124 server.socket.data.write "\004\b\"\bbar\r\n" 125 server.socket.data.write "END\r\n" 126 server.socket.data.rewind 127 128 result = @cache.cache_get_multi server, 'foo bar baz' 129 130 assert_equal 2, result.length 131 assert_equal "\004\b\"\bfoo", result['foo'] 132 assert_equal "\004\b\"\bbar", result['bar'] 133 end 134 135 def test_cache_get_multi_EOF 136 server = util_setup_fake_server 137 server.socket.data.string = '' 138 139 e = assert_raise MemCache::MemCacheError do 140 @cache.cache_get_multi server, 'my_namespace:key' 141 end 142 143 assert_equal "lost connection to example.com:11211", e.message 144 end 145 146 def test_cache_get_multi_bad_state 147 server = FakeServer.new 148 server.socket.data.write "bogus response\r\n" 149 server.socket.data.rewind 150 151 @cache.servers = [] 152 @cache.servers << server 153 154 e = assert_raise MemCache::MemCacheError do 155 @cache.cache_get_multi server, 'my_namespace:key' 156 end 157 158 assert_equal "unexpected response \"bogus response\\r\\n\"", e.message 159 160 deny server.alive? 161 162 assert_equal "get my_namespace:key\r\n", 163 server.socket.written.string 164 end 165 166 def test_crc32_ITU_T 167 assert_equal 0, ''.crc32_ITU_T 168 assert_equal 1260851911, 'my_namespace:key'.crc32_ITU_T 169 end 170 171 def test_initialize 172 cache = MemCache.new :namespace => 'my_namespace', :readonly => true 173 174 assert_equal 'my_namespace', cache.namespace 175 assert_equal true, cache.readonly? 176 assert_equal true, cache.servers.empty? 177 end 178 179 def test_initialize_compatible 180 cache = MemCache.new ['localhost:11211', 'localhost:11212'], 181 :namespace => 'my_namespace', :readonly => true 182 183 assert_equal 'my_namespace', cache.namespace 184 assert_equal true, cache.readonly? 185 assert_equal false, cache.servers.empty? 186 end 187 188 def test_initialize_compatible_no_hash 189 cache = MemCache.new ['localhost:11211', 'localhost:11212'] 190 191 assert_equal nil, cache.namespace 192 assert_equal false, cache.readonly? 193 assert_equal false, cache.servers.empty? 194 end 195 196 def test_initialize_compatible_one_server 197 cache = MemCache.new 'localhost:11211' 198 199 assert_equal nil, cache.namespace 200 assert_equal false, cache.readonly? 201 assert_equal false, cache.servers.empty? 202 end 203 204 def test_initialize_compatible_bad_arg 205 e = assert_raise ArgumentError do 206 cache = MemCache.new Object.new 207 end 208 209 assert_equal 'first argument must be Array, Hash or String', e.message 210 end 211 212 def test_initialize_multiple_servers 213 cache = MemCache.new %w[localhost:11211 localhost:11212], 214 :namespace => 'my_namespace', :readonly => true 215 216 assert_equal 'my_namespace', cache.namespace 217 assert_equal true, cache.readonly? 218 assert_equal false, cache.servers.empty? 219 deny_empty cache.instance_variable_get(:@buckets) 220 end 221 222 def test_initialize_too_many_args 223 assert_raises ArgumentError do 224 MemCache.new 1, 2, 3 225 end 226 end 227 228 def test_decr 229 server = FakeServer.new 230 server.socket.data.write "5\r\n" 231 server.socket.data.rewind 232 233 @cache.servers = [] 234 @cache.servers << server 235 236 value = @cache.decr 'key' 237 238 assert_equal "decr my_namespace:key 1\r\n", 239 @cache.servers.first.socket.written.string 240 241 assert_equal 5, value 242 end 243 244 def test_decr_not_found 245 server = FakeServer.new 246 server.socket.data.write "NOT_FOUND\r\n" 247 server.socket.data.rewind 248 249 @cache.servers = [] 250 @cache.servers << server 251 252 value = @cache.decr 'key' 253 254 assert_equal "decr my_namespace:key 1\r\n", 255 @cache.servers.first.socket.written.string 256 257 assert_equal nil, value 258 end 259 260 def test_decr_space_padding 261 server = FakeServer.new 262 server.socket.data.write "5 \r\n" 263 server.socket.data.rewind 264 265 @cache.servers = [] 266 @cache.servers << server 267 268 value = @cache.decr 'key' 269 270 assert_equal "decr my_namespace:key 1\r\n", 271 @cache.servers.first.socket.written.string 272 273 assert_equal 5, value 274 end 275 276 def test_get 277 util_setup_fake_server 278 279 value = @cache.get 'key' 280 281 assert_equal "get my_namespace:key\r\n", 282 @cache.servers.first.socket.written.string 283 284 assert_equal '0123456789', value 285 end 286 287 def test_get_bad_key 288 util_setup_fake_server 289 assert_raise ArgumentError do @cache.get 'k y' end 290 291 util_setup_fake_server 292 assert_raise ArgumentError do @cache.get 'k' * 250 end 293 end 294 295 def test_get_cache_get_IOError 296 socket = Object.new 297 def socket.write(arg) raise IOError, 'some io error'; end 298 server = FakeServer.new socket 299 300 @cache.servers = [] 301 @cache.servers << server 302 303 e = assert_raise MemCache::MemCacheError do 304 @cache.get 'my_namespace:key' 305 end 306 307 assert_equal 'some io error', e.message 308 end 309 310 def test_get_cache_get_SystemCallError 311 socket = Object.new 312 def socket.write(arg) raise SystemCallError, 'some syscall error'; end 313 server = FakeServer.new socket 314 315 @cache.servers = [] 316 @cache.servers << server 317 318 e = assert_raise MemCache::MemCacheError do 319 @cache.get 'my_namespace:key' 320 end 321 322 assert_equal 'unknown error - some syscall error', e.message 323 end 324 325 def test_get_no_connection 326 @cache.servers = 'localhost:1' 327 e = assert_raise MemCache::MemCacheError do 328 @cache.get 'key' 329 end 330 331 assert_match /^No connection to server/, e.message 332 end 333 334 def test_get_no_servers 335 @cache.servers = [] 336 e = assert_raise MemCache::MemCacheError do 337 @cache.get 'key' 338 end 339 340 assert_equal 'No active servers', e.message 341 end 342 343 def test_get_multi 344 server = FakeServer.new 345 server.socket.data.write "VALUE my_namespace:key 0 14\r\n" 346 server.socket.data.write "\004\b\"\0170123456789\r\n" 347 server.socket.data.write "VALUE my_namespace:keyb 0 14\r\n" 348 server.socket.data.write "\004\b\"\0179876543210\r\n" 349 server.socket.data.write "END\r\n" 350 server.socket.data.rewind 351 352 @cache.servers = [] 353 @cache.servers << server 354 355 values = @cache.get_multi 'key', 'keyb' 356 357 assert_equal "get my_namespace:key my_namespace:keyb\r\n", 358 server.socket.written.string 359 360 expected = { 'key' => '0123456789', 'keyb' => '9876543210' } 361 362 assert_equal expected.sort, values.sort 363 end 364 365 def test_get_raw 366 server = FakeServer.new 367 server.socket.data.write "VALUE my_namespace:key 0 10\r\n" 368 server.socket.data.write "0123456789\r\n" 369 server.socket.data.write "END\r\n" 370 server.socket.data.rewind 371 372 @cache.servers = [] 373 @cache.servers << server 374 375 376 value = @cache.get 'key', true 377 378 assert_equal "get my_namespace:key\r\n", 379 @cache.servers.first.socket.written.string 380 381 assert_equal '0123456789', value 382 end 383 384 def test_get_server_for_key 385 server = @cache.get_server_for_key 'key' 386 assert_equal 'localhost', server.host 387 assert_equal 1, server.port 388 end 389 390 def test_get_server_for_key_multiple 391 s1 = util_setup_server @cache, 'one.example.com', '' 392 s2 = util_setup_server @cache, 'two.example.com', '' 393 @cache.instance_variable_set :@servers, [s1, s2] 394 @cache.instance_variable_set :@buckets, [s1, s2] 395 396 server = @cache.get_server_for_key 'keya' 397 assert_equal 'two.example.com', server.host 398 server = @cache.get_server_for_key 'keyb' 399 assert_equal 'one.example.com', server.host 400 end 401 402 def test_get_server_for_key_no_servers 403 @cache.servers = [] 404 405 e = assert_raise MemCache::MemCacheError do 406 @cache.get_server_for_key 'key' 407 end 408 409 assert_equal 'No servers available', e.message 410 end 411 412 def test_get_server_for_key_spaces 413 e = assert_raise ArgumentError do 414 @cache.get_server_for_key 'space key' 415 end 416 assert_equal 'illegal character in key "space key"', e.message 417 end 418 419 def test_get_server_for_key_length 420 @cache.get_server_for_key 'x' * 250 421 long_key = 'x' * 251 422 e = assert_raise ArgumentError do 423 @cache.get_server_for_key long_key 424 end 425 assert_equal "key too long #{long_key.inspect}", e.message 426 end 427 428 def test_incr 429 server = FakeServer.new 430 server.socket.data.write "5\r\n" 431 server.socket.data.rewind 432 433 @cache.servers = [] 434 @cache.servers << server 435 436 value = @cache.incr 'key' 437 438 assert_equal "incr my_namespace:key 1\r\n", 439 @cache.servers.first.socket.written.string 440 441 assert_equal 5, value 442 end 443 444 def test_incr_not_found 445 server = FakeServer.new 446 server.socket.data.write "NOT_FOUND\r\n" 447 server.socket.data.rewind 448 449 @cache.servers = [] 450 @cache.servers << server 451 452 value = @cache.incr 'key' 453 454 assert_equal "incr my_namespace:key 1\r\n", 455 @cache.servers.first.socket.written.string 456 457 assert_equal nil, value 458 end 459 460 def test_incr_space_padding 461 server = FakeServer.new 462 server.socket.data.write "5 \r\n" 463 server.socket.data.rewind 464 465 @cache.servers = [] 466 @cache.servers << server 467 468 value = @cache.incr 'key' 469 470 assert_equal "incr my_namespace:key 1\r\n", 471 @cache.servers.first.socket.written.string 472 473 assert_equal 5, value 474 end 475 476 def test_make_cache_key 477 assert_equal 'my_namespace:key', @cache.make_cache_key('key') 478 @cache.namespace = nil 479 assert_equal 'key', @cache.make_cache_key('key') 480 end 481 482 def test_servers 483 server = FakeServer.new 484 @cache.servers = [] 485 @cache.servers << server 486 assert_equal [server], @cache.servers 487 end 488 489 def test_servers_equals_type_error 490 e = assert_raise TypeError do 491 @cache.servers = [Object.new] 492 end 493 494 assert_equal 'cannot convert Object into MemCache::Server', e.message 495 end 496 497 def test_set 498 server = FakeServer.new 499 server.socket.data.write "STORED\r\n" 500 server.socket.data.rewind 501 @cache.servers = [] 502 @cache.servers << server 503 504 @cache.set 'key', 'value' 505 506 expected = "set my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n" 507 assert_equal expected, server.socket.written.string 508 end 509 510 def test_set_expiry 511 server = FakeServer.new 512 server.socket.data.write "STORED\r\n" 513 server.socket.data.rewind 514 @cache.servers = [] 515 @cache.servers << server 516 517 @cache.set 'key', 'value', 5 518 519 expected = "set my_namespace:key 0 5 9\r\n\004\b\"\nvalue\r\n" 520 assert_equal expected, server.socket.written.string 521 end 522 523 def test_set_raw 524 server = FakeServer.new 525 server.socket.data.write "STORED\r\n" 526 server.socket.data.rewind 527 @cache.servers = [] 528 @cache.servers << server 529 530 @cache.set 'key', 'value', 0, true 531 532 expected = "set my_namespace:key 0 0 5\r\nvalue\r\n" 533 assert_equal expected, server.socket.written.string 534 end 535 536 def test_set_readonly 537 cache = MemCache.new :readonly => true 538 539 e = assert_raise MemCache::MemCacheError do 540 cache.set 'key', 'value' 541 end 542 543 assert_equal 'Update of readonly cache', e.message 544 end 545 546 def test_set_too_big 547 server = FakeServer.new 548 server.socket.data.write "SERVER_ERROR object too large for cache\r\n" 549 server.socket.data.rewind 550 @cache.servers = [] 551 @cache.servers << server 552 553 e = assert_raise MemCache::MemCacheError do 554 @cache.set 'key', 'v' 555 end 556 557 assert_equal 'object too large for cache', e.message 558 end 559 560 def test_add 561 server = FakeServer.new 562 server.socket.data.write "STORED\r\n" 563 server.socket.data.rewind 564 @cache.servers = [] 565 @cache.servers << server 566 567 @cache.add 'key', 'value' 568 569 expected = "add my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n" 570 assert_equal expected, server.socket.written.string 571 end 572 573 def test_add_exists 574 server = FakeServer.new 575 server.socket.data.write "NOT_STORED\r\n" 576 server.socket.data.rewind 577 @cache.servers = [] 578 @cache.servers << server 579 580 @cache.add 'key', 'value' 581 582 expected = "add my_namespace:key 0 0 9\r\n\004\b\"\nvalue\r\n" 583 assert_equal expected, server.socket.written.string 584 end 585 586 def test_add_expiry 587 server = FakeServer.new 588 server.socket.data.write "STORED\r\n" 589 server.socket.data.rewind 590 @cache.servers = [] 591 @cache.servers << server 592 593 @cache.add 'key', 'value', 5 594 595 expected = "add my_namespace:key 0 5 9\r\n\004\b\"\nvalue\r\n" 596 assert_equal expected, server.socket.written.string 597 end 598 599 def test_add_raw 600 server = FakeServer.new 601 server.socket.data.write "STORED\r\n" 602 server.socket.data.rewind 603 @cache.servers = [] 604 @cache.servers << server 605 606 @cache.add 'key', 'value', 0, true 607 608 expected = "add my_namespace:key 0 0 5\r\nvalue\r\n" 609 assert_equal expected, server.socket.written.string 610 end 611 612 def test_add_readonly 613 cache = MemCache.new :readonly => true 614 615 e = assert_raise MemCache::MemCacheError do 616 cache.add 'key', 'value' 617 end 618 619 assert_equal 'Update of readonly cache', e.message 620 end 621 622 def test_delete 623 server = FakeServer.new 624 @cache.servers = [] 625 @cache.servers << server 626 627 @cache.delete 'key' 628 629 expected = "delete my_namespace:key 0\r\n" 630 assert_equal expected, server.socket.written.string 631 end 632 633 def test_delete_with_expiry 634 server = FakeServer.new 635 @cache.servers = [] 636 @cache.servers << server 637 638 @cache.delete 'key', 300 639 640 expected = "delete my_namespace:key 300\r\n" 641 assert_equal expected, server.socket.written.string 642 end 643 644 def test_flush_all 645 @cache.servers = [] 646 3.times { @cache.servers << FakeServer.new } 647 648 @cache.flush_all 649 650 expected = "flush_all\r\n" 651 @cache.servers.each do |server| 652 assert_equal expected, server.socket.written.string 653 end 654 end 655 656 def test_flush_all_failure 657 socket = FakeSocket.new 658 socket.data.write "ERROR\r\n" 659 socket.data.rewind 660 server = FakeServer.new socket 661 def server.host() "localhost"; end 662 def server.port() 11211; end 663 664 @cache.servers = [] 665 @cache.servers << server 666 667 assert_raise MemCache::MemCacheError do 668 @cache.flush_all 669 end 670 671 assert_equal "flush_all\r\n", socket.written.string 672 end 673 674 def test_stats 675 socket = FakeSocket.new 676 socket.data.write "STAT pid 20188\r\nSTAT total_items 32\r\nSTAT version 1.2.3\r\nSTAT rusage_user 1:300\r\nSTAT dummy ok\r\nEND\r\n" 677 socket.data.rewind 678 server = FakeServer.new socket 679 def server.host() 'localhost'; end 680 def server.port() 11211; end 681 682 @cache.servers = [] 683 @cache.servers << server 684 685 expected = { 686 'localhost:11211' => { 687 'pid' => 20188, 'total_items' => 32, 'version' => '1.2.3', 688 'rusage_user' => 1.0003, 'dummy' => 'ok' 689 } 690 } 691 assert_equal expected, @cache.stats 692 693 assert_equal "stats\r\n", socket.written.string 694 end 695 696 def test_basic_threaded_operations_should_work 697 cache = MemCache.new :multithread => true, 698 :namespace => 'my_namespace', 699 :readonly => false 700 server = util_setup_server cache, 'example.com', "OK\r\n" 701 cache.instance_variable_set :@servers, [server] 702 703 assert_nothing_raised do 704 cache.set "test", "test value" 705 end 706 end 707 708 def test_basic_unthreaded_operations_should_work 709 cache = MemCache.new :multithread => false, 710 :namespace => 'my_namespace', 711 :readonly => false 712 server = util_setup_server cache, 'example.com', "OK\r\n" 713 cache.instance_variable_set :@servers, [server] 714 715 assert_nothing_raised do 716 cache.set "test", "test value" 717 end 718 end 719 720 def util_setup_fake_server 721 server = FakeServer.new 722 server.socket.data.write "VALUE my_namespace:key 0 14\r\n" 723 server.socket.data.write "\004\b\"\0170123456789\r\n" 724 server.socket.data.write "END\r\n" 725 server.socket.data.rewind 726 727 @cache.servers = [] 728 @cache.servers << server 729 730 return server 731 end 732 733 def util_setup_server(memcache, host, responses) 734 server = MemCache::Server.new memcache, host 735 server.instance_variable_set :@sock, StringIO.new(responses) 736 737 @cache.servers = [] 738 @cache.servers << server 739 740 return server 741 end 742 743end 744