1#!/usr/bin/env perl 2 3use strict; 4use Test::More tests => 113; 5use FindBin qw($Bin); 6use lib "$Bin/lib"; 7use MemcachedTest; 8 9my $server = new_memcached("-I 1024 -o slab_chunk_max=1,no_lru_crawler,no_lru_maintainer"); 10my $sock = $server->sock; 11 12 13## Output looks like this: 14## 15## STAT pid 22969 16## STAT uptime 13 17## STAT time 1259170891 18## STAT version 1.4.3 19## STAT libevent 1.4.13-stable. 20## see doc/protocol.txt for others 21# note that auth stats are tested in auth specific tests 22 23 24my $stats = mem_stats($sock); 25 26# Test number of keys 27if (MemcachedTest::enabled_tls_testing()) { 28 # when TLS is enabled, stats contains additional keys: 29 # - ssl_handshake_errors 30 # - time_since_server_cert_refresh 31 is(scalar(keys(%$stats)), 85, "expected count of stats values"); 32} else { 33 is(scalar(keys(%$stats)), 83, "expected count of stats values"); 34} 35 36# Test initial state 37foreach my $key (qw(curr_items total_items bytes cmd_get cmd_set get_hits evictions get_misses get_expired 38 bytes_written delete_hits delete_misses incr_hits incr_misses decr_hits get_flushed 39 decr_misses listen_disabled_num lrutail_reflocked time_in_listen_disabled_us 40 store_too_large store_no_memory)) { 41 is($stats->{$key}, 0, "initial $key is zero"); 42} 43is($stats->{accepting_conns}, 1, "initial accepting_conns is one"); 44 45# Do some operations 46 47print $sock "set foo 0 0 6\r\nfooval\r\n"; 48is(scalar <$sock>, "STORED\r\n", "stored foo"); 49mem_get_is($sock, "foo", "fooval"); 50 51my $stats = mem_stats($sock); 52 53foreach my $key (qw(total_items curr_items cmd_get cmd_set get_hits)) { 54 is($stats->{$key}, 1, "after one set/one get $key is 1"); 55} 56 57my $cache_dump = mem_stats($sock, " cachedump 1 100"); 58ok(defined $cache_dump->{'foo'}, "got foo from cachedump"); 59 60print $sock "delete foo\r\n"; 61is(scalar <$sock>, "DELETED\r\n", "deleted foo"); 62 63my $stats = mem_stats($sock); 64is($stats->{delete_hits}, 1); 65is($stats->{delete_misses}, 0); 66 67print $sock "delete foo\r\n"; 68is(scalar <$sock>, "NOT_FOUND\r\n", "shouldn't delete foo again"); 69 70my $stats = mem_stats($sock); 71is($stats->{delete_hits}, 1); 72is($stats->{delete_misses}, 1); 73 74# incr stats 75 76sub check_incr_stats { 77 my ($ih, $im, $dh, $dm) = @_; 78 my $stats = mem_stats($sock); 79 80 is($stats->{incr_hits}, $ih); 81 is($stats->{incr_misses}, $im); 82 is($stats->{decr_hits}, $dh); 83 is($stats->{decr_misses}, $dm); 84} 85 86print $sock "incr i 1\r\n"; 87is(scalar <$sock>, "NOT_FOUND\r\n", "shouldn't incr a missing thing"); 88check_incr_stats(0, 1, 0, 0); 89 90print $sock "decr d 1\r\n"; 91is(scalar <$sock>, "NOT_FOUND\r\n", "shouldn't decr a missing thing"); 92check_incr_stats(0, 1, 0, 1); 93 94print $sock "set n 0 0 1\r\n0\r\n"; 95is(scalar <$sock>, "STORED\r\n", "stored n"); 96 97print $sock "incr n 3\r\n"; 98is(scalar <$sock>, "3\r\n", "incr works"); 99check_incr_stats(1, 1, 0, 1); 100 101print $sock "decr n 1\r\n"; 102is(scalar <$sock>, "2\r\n", "decr works"); 103check_incr_stats(1, 1, 1, 1); 104 105# cas stats 106 107sub check_cas_stats { 108 my ($ch, $cm, $cb) = @_; 109 my $stats = mem_stats($sock); 110 111 is($stats->{cas_hits}, $ch); 112 is($stats->{cas_misses}, $cm); 113 is($stats->{cas_badval}, $cb); 114} 115 116check_cas_stats(0, 0, 0); 117 118print $sock "cas c 0 0 1 99999999\r\nz\r\n"; 119is(scalar <$sock>, "NOT_FOUND\r\n", "missed cas"); 120check_cas_stats(0, 1, 0); 121 122print $sock "set c 0 0 1\r\nx\r\n"; 123is(scalar <$sock>, "STORED\r\n", "stored c"); 124my ($id, $v) = mem_gets($sock, 'c'); 125is('x', $v, 'got the expected value'); 126 127print $sock "cas c 0 0 1 99999999\r\nz\r\n"; 128is(scalar <$sock>, "EXISTS\r\n", "missed cas"); 129check_cas_stats(0, 1, 1); 130my ($newid, $v) = mem_gets($sock, 'c'); 131is('x', $v, 'got the expected value'); 132 133print $sock "cas c 0 0 1 $id\r\nz\r\n"; 134is(scalar <$sock>, "STORED\r\n", "good cas"); 135check_cas_stats(1, 1, 1); 136my ($newid, $v) = mem_gets($sock, 'c'); 137is('z', $v, 'got the expected value'); 138 139my $settings = mem_stats($sock, ' settings'); 140is(1024, $settings->{'maxconns'}); 141# we run SSL tests over TCP; hence the domain_socket 142# is expected to be NULL. 143if (enabled_tls_testing() || !supports_unix_socket()) { 144 is('NULL', $settings->{'domain_socket'}); 145} else { 146 isnt('NULL', $settings->{'domain_socket'}); 147} 148is('on', $settings->{'evictions'}); 149is('yes', $settings->{'cas_enabled'}); 150is('no', $settings->{'auth_enabled_sasl'}); 151is('no', $settings->{'shutdown_command'}); 152 153print $sock "stats reset\r\n"; 154is(scalar <$sock>, "RESET\r\n", "good stats reset"); 155 156my $stats = mem_stats($sock); 157is(0, $stats->{'cmd_get'}); 158is(0, $stats->{'cmd_set'}); 159is(0, $stats->{'get_hits'}); 160is(0, $stats->{'get_misses'}); 161is(0, $stats->{'get_expired'}); 162is(0, $stats->{'get_flushed'}); 163is(0, $stats->{'delete_misses'}); 164is(0, $stats->{'delete_hits'}); 165is(0, $stats->{'incr_misses'}); 166is(0, $stats->{'incr_hits'}); 167is(0, $stats->{'decr_misses'}); 168is(0, $stats->{'decr_hits'}); 169is(0, $stats->{'cas_misses'}); 170is(0, $stats->{'cas_hits'}); 171is(0, $stats->{'cas_badval'}); 172is(0, $stats->{'evictions'}); 173is(0, $stats->{'reclaimed'}); 174is(0, $stats->{'lrutail_reflocked'}); 175 176# item expired 177print $sock "set should_expire 0 2678400 6\r\nfooval\r\n"; #2678400 = 31 days in seconds 178is(scalar <$sock>, "STORED\r\n", "set item to expire"); 179print $sock "get should_expire\r\n"; 180is(scalar <$sock>, "END\r\n", "item not returned"); 181my $stats = mem_stats($sock); 182is(1, $stats->{'get_expired'}, "get_expired counter is 1"); 183 184print $sock "set should_be_flushed 0 0 6\r\nbooval\r\n"; 185is(scalar <$sock>, "STORED\r\n", "set item to flush"); 186mem_move_time($sock, 3); # need to wait so `flush_all` doesn't nuke the item. 187print $sock "flush_all\r\n"; 188is(scalar <$sock>, "OK\r\n", "flushed"); 189print $sock "get should_be_flushed\r\n"; 190is(scalar <$sock>, "END\r\n", "flushed item not returned"); 191 192my $stats = mem_stats($sock); 193is($stats->{cmd_flush}, 1, "after one flush cmd_flush is 1"); 194is($stats->{get_flushed}, 1, "after flush and a get, get_flushed is 1"); 195 196# item too large 197my $large = "B" x 2048; 198my $largelen = length($large); 199print $sock "set too_large 0 0 $largelen\r\n$large\r\n"; 200is(scalar <$sock>, "SERVER_ERROR object too large for cache\r\n", 201 "set rejected due to value too large"); 202$stats = mem_stats($sock); 203is($stats->{'store_too_large'}, 1, 204 "recorded store failure due to value too large") 205