couchbase-memcached 1.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (539) hide show
  1. data.tar.gz.sig +2 -0
  2. data/BENCHMARKS +134 -0
  3. data/CHANGELOG +127 -0
  4. data/LICENSE +184 -0
  5. data/Manifest +535 -0
  6. data/README +118 -0
  7. data/Rakefile +83 -0
  8. data/TODO +4 -0
  9. data/couchbase-memcached.gemspec +33 -0
  10. data/ext/extconf-make.rb +25 -0
  11. data/ext/extconf.rb +91 -0
  12. data/ext/libmemcached-0.50/AUTHORS +11 -0
  13. data/ext/libmemcached-0.50/COPYING +33 -0
  14. data/ext/libmemcached-0.50/ChangeLog +392 -0
  15. data/ext/libmemcached-0.50/Makefile.am +114 -0
  16. data/ext/libmemcached-0.50/Makefile.in +4232 -0
  17. data/ext/libmemcached-0.50/NEWS +1 -0
  18. data/ext/libmemcached-0.50/README +43 -0
  19. data/ext/libmemcached-0.50/README.FIRST +31 -0
  20. data/ext/libmemcached-0.50/README.win32 +25 -0
  21. data/ext/libmemcached-0.50/THANKS +14 -0
  22. data/ext/libmemcached-0.50/TODO +11 -0
  23. data/ext/libmemcached-0.50/aclocal.m4 +1077 -0
  24. data/ext/libmemcached-0.50/clients/client_options.h +45 -0
  25. data/ext/libmemcached-0.50/clients/execute.cc +131 -0
  26. data/ext/libmemcached-0.50/clients/execute.h +30 -0
  27. data/ext/libmemcached-0.50/clients/generator.cc +96 -0
  28. data/ext/libmemcached-0.50/clients/generator.h +36 -0
  29. data/ext/libmemcached-0.50/clients/include.am +116 -0
  30. data/ext/libmemcached-0.50/clients/memaslap.c +908 -0
  31. data/ext/libmemcached-0.50/clients/memcapable.cc +2094 -0
  32. data/ext/libmemcached-0.50/clients/memcat.cc +242 -0
  33. data/ext/libmemcached-0.50/clients/memcp.cc +317 -0
  34. data/ext/libmemcached-0.50/clients/memdump.cc +183 -0
  35. data/ext/libmemcached-0.50/clients/memerror.cc +102 -0
  36. data/ext/libmemcached-0.50/clients/memflush.cc +154 -0
  37. data/ext/libmemcached-0.50/clients/memparse.cc +68 -0
  38. data/ext/libmemcached-0.50/clients/memrm.cc +177 -0
  39. data/ext/libmemcached-0.50/clients/memslap.cc +495 -0
  40. data/ext/libmemcached-0.50/clients/memstat.cc +349 -0
  41. data/ext/libmemcached-0.50/clients/ms_atomic.h +69 -0
  42. data/ext/libmemcached-0.50/clients/ms_conn.c +3413 -0
  43. data/ext/libmemcached-0.50/clients/ms_conn.h +241 -0
  44. data/ext/libmemcached-0.50/clients/ms_memslap.h +132 -0
  45. data/ext/libmemcached-0.50/clients/ms_setting.c +1068 -0
  46. data/ext/libmemcached-0.50/clients/ms_setting.h +181 -0
  47. data/ext/libmemcached-0.50/clients/ms_sigsegv.c +126 -0
  48. data/ext/libmemcached-0.50/clients/ms_sigsegv.h +34 -0
  49. data/ext/libmemcached-0.50/clients/ms_stats.c +307 -0
  50. data/ext/libmemcached-0.50/clients/ms_stats.h +69 -0
  51. data/ext/libmemcached-0.50/clients/ms_task.c +1114 -0
  52. data/ext/libmemcached-0.50/clients/ms_task.h +94 -0
  53. data/ext/libmemcached-0.50/clients/ms_thread.c +351 -0
  54. data/ext/libmemcached-0.50/clients/ms_thread.h +78 -0
  55. data/ext/libmemcached-0.50/clients/utilities.cc +231 -0
  56. data/ext/libmemcached-0.50/clients/utilities.h +64 -0
  57. data/ext/libmemcached-0.50/config.h.in +647 -0
  58. data/ext/libmemcached-0.50/config/autorun.sh +126 -0
  59. data/ext/libmemcached-0.50/config/compile +143 -0
  60. data/ext/libmemcached-0.50/config/config.guess +1517 -0
  61. data/ext/libmemcached-0.50/config/config.rpath +666 -0
  62. data/ext/libmemcached-0.50/config/config.sub +1760 -0
  63. data/ext/libmemcached-0.50/config/depcomp +630 -0
  64. data/ext/libmemcached-0.50/config/install-sh +520 -0
  65. data/ext/libmemcached-0.50/config/ltmain.sh +9642 -0
  66. data/ext/libmemcached-0.50/config/missing +376 -0
  67. data/ext/libmemcached-0.50/config/pandora-plugin +752 -0
  68. data/ext/libmemcached-0.50/config/uncrustify.cfg +1112 -0
  69. data/ext/libmemcached-0.50/configure +27103 -0
  70. data/ext/libmemcached-0.50/configure.ac +186 -0
  71. data/ext/libmemcached-0.50/docs/conf.py.in +354 -0
  72. data/ext/libmemcached-0.50/docs/include.am +240 -0
  73. data/ext/libmemcached-0.50/docs/man/hashkit_clone.3 +88 -0
  74. data/ext/libmemcached-0.50/docs/man/hashkit_crc32.3 +105 -0
  75. data/ext/libmemcached-0.50/docs/man/hashkit_create.3 +88 -0
  76. data/ext/libmemcached-0.50/docs/man/hashkit_fnv1_32.3 +105 -0
  77. data/ext/libmemcached-0.50/docs/man/hashkit_fnv1_64.3 +105 -0
  78. data/ext/libmemcached-0.50/docs/man/hashkit_fnv1a_32.3 +105 -0
  79. data/ext/libmemcached-0.50/docs/man/hashkit_fnv1a_64.3 +105 -0
  80. data/ext/libmemcached-0.50/docs/man/hashkit_free.3 +88 -0
  81. data/ext/libmemcached-0.50/docs/man/hashkit_functions.3 +105 -0
  82. data/ext/libmemcached-0.50/docs/man/hashkit_hsieh.3 +105 -0
  83. data/ext/libmemcached-0.50/docs/man/hashkit_is_allocated.3 +88 -0
  84. data/ext/libmemcached-0.50/docs/man/hashkit_jenkins.3 +105 -0
  85. data/ext/libmemcached-0.50/docs/man/hashkit_md5.3 +105 -0
  86. data/ext/libmemcached-0.50/docs/man/hashkit_murmur.3 +105 -0
  87. data/ext/libmemcached-0.50/docs/man/hashkit_value.3 +66 -0
  88. data/ext/libmemcached-0.50/docs/man/libhashkit.3 +57 -0
  89. data/ext/libmemcached-0.50/docs/man/libmemcached.3 +208 -0
  90. data/ext/libmemcached-0.50/docs/man/libmemcached_check_configuration.3 +293 -0
  91. data/ext/libmemcached-0.50/docs/man/libmemcached_configuration.3 +293 -0
  92. data/ext/libmemcached-0.50/docs/man/libmemcached_examples.3 +144 -0
  93. data/ext/libmemcached-0.50/docs/man/libmemcachedutil.3 +68 -0
  94. data/ext/libmemcached-0.50/docs/man/memaslap.1 +1222 -0
  95. data/ext/libmemcached-0.50/docs/man/memcached.3 +293 -0
  96. data/ext/libmemcached-0.50/docs/man/memcached_add.3 +132 -0
  97. data/ext/libmemcached-0.50/docs/man/memcached_add_by_key.3 +132 -0
  98. data/ext/libmemcached-0.50/docs/man/memcached_analyze.3 +77 -0
  99. data/ext/libmemcached-0.50/docs/man/memcached_append.3 +111 -0
  100. data/ext/libmemcached-0.50/docs/man/memcached_append_by_key.3 +111 -0
  101. data/ext/libmemcached-0.50/docs/man/memcached_behavior_get.3 +333 -0
  102. data/ext/libmemcached-0.50/docs/man/memcached_behavior_set.3 +333 -0
  103. data/ext/libmemcached-0.50/docs/man/memcached_callback_get.3 +159 -0
  104. data/ext/libmemcached-0.50/docs/man/memcached_callback_set.3 +159 -0
  105. data/ext/libmemcached-0.50/docs/man/memcached_cas.3 +91 -0
  106. data/ext/libmemcached-0.50/docs/man/memcached_cas_by_key.3 +91 -0
  107. data/ext/libmemcached-0.50/docs/man/memcached_clone.3 +99 -0
  108. data/ext/libmemcached-0.50/docs/man/memcached_create.3 +99 -0
  109. data/ext/libmemcached-0.50/docs/man/memcached_decrement.3 +124 -0
  110. data/ext/libmemcached-0.50/docs/man/memcached_decrement_with_initial.3 +124 -0
  111. data/ext/libmemcached-0.50/docs/man/memcached_delete.3 +83 -0
  112. data/ext/libmemcached-0.50/docs/man/memcached_delete_by_key.3 +83 -0
  113. data/ext/libmemcached-0.50/docs/man/memcached_destroy_sasl_auth_data.3 +95 -0
  114. data/ext/libmemcached-0.50/docs/man/memcached_dump.3 +77 -0
  115. data/ext/libmemcached-0.50/docs/man/memcached_fetch.3 +174 -0
  116. data/ext/libmemcached-0.50/docs/man/memcached_fetch_execute.3 +174 -0
  117. data/ext/libmemcached-0.50/docs/man/memcached_fetch_result.3 +174 -0
  118. data/ext/libmemcached-0.50/docs/man/memcached_flush_buffers.3 +72 -0
  119. data/ext/libmemcached-0.50/docs/man/memcached_free.3 +99 -0
  120. data/ext/libmemcached-0.50/docs/man/memcached_generate_hash.3 +85 -0
  121. data/ext/libmemcached-0.50/docs/man/memcached_generate_hash_value.3 +85 -0
  122. data/ext/libmemcached-0.50/docs/man/memcached_get.3 +174 -0
  123. data/ext/libmemcached-0.50/docs/man/memcached_get_by_key.3 +174 -0
  124. data/ext/libmemcached-0.50/docs/man/memcached_get_memory_allocators.3 +111 -0
  125. data/ext/libmemcached-0.50/docs/man/memcached_get_sasl_callbacks.3 +95 -0
  126. data/ext/libmemcached-0.50/docs/man/memcached_get_user_data.3 +79 -0
  127. data/ext/libmemcached-0.50/docs/man/memcached_increment.3 +124 -0
  128. data/ext/libmemcached-0.50/docs/man/memcached_increment_with_initial.3 +124 -0
  129. data/ext/libmemcached-0.50/docs/man/memcached_lib_version.3 +76 -0
  130. data/ext/libmemcached-0.50/docs/man/memcached_mget.3 +174 -0
  131. data/ext/libmemcached-0.50/docs/man/memcached_mget_by_key.3 +174 -0
  132. data/ext/libmemcached-0.50/docs/man/memcached_mget_execute.3 +174 -0
  133. data/ext/libmemcached-0.50/docs/man/memcached_mget_execute_by_key.3 +174 -0
  134. data/ext/libmemcached-0.50/docs/man/memcached_pool_behavior_get.3 +139 -0
  135. data/ext/libmemcached-0.50/docs/man/memcached_pool_behavior_set.3 +139 -0
  136. data/ext/libmemcached-0.50/docs/man/memcached_pool_create.3 +139 -0
  137. data/ext/libmemcached-0.50/docs/man/memcached_pool_destroy.3 +139 -0
  138. data/ext/libmemcached-0.50/docs/man/memcached_pool_pop.3 +139 -0
  139. data/ext/libmemcached-0.50/docs/man/memcached_pool_push.3 +139 -0
  140. data/ext/libmemcached-0.50/docs/man/memcached_pool_st.3 +139 -0
  141. data/ext/libmemcached-0.50/docs/man/memcached_prepend.3 +111 -0
  142. data/ext/libmemcached-0.50/docs/man/memcached_prepend_by_key.3 +111 -0
  143. data/ext/libmemcached-0.50/docs/man/memcached_quit.3 +74 -0
  144. data/ext/libmemcached-0.50/docs/man/memcached_replace.3 +132 -0
  145. data/ext/libmemcached-0.50/docs/man/memcached_replace_by_key.3 +132 -0
  146. data/ext/libmemcached-0.50/docs/man/memcached_sasl_set_auth_data.3 +95 -0
  147. data/ext/libmemcached-0.50/docs/man/memcached_server_add.3 +141 -0
  148. data/ext/libmemcached-0.50/docs/man/memcached_server_count.3 +141 -0
  149. data/ext/libmemcached-0.50/docs/man/memcached_server_cursor.3 +141 -0
  150. data/ext/libmemcached-0.50/docs/man/memcached_server_list.3 +141 -0
  151. data/ext/libmemcached-0.50/docs/man/memcached_server_list_append.3 +111 -0
  152. data/ext/libmemcached-0.50/docs/man/memcached_server_list_count.3 +111 -0
  153. data/ext/libmemcached-0.50/docs/man/memcached_server_list_free.3 +111 -0
  154. data/ext/libmemcached-0.50/docs/man/memcached_server_push.3 +141 -0
  155. data/ext/libmemcached-0.50/docs/man/memcached_servers_parse.3 +111 -0
  156. data/ext/libmemcached-0.50/docs/man/memcached_set.3 +132 -0
  157. data/ext/libmemcached-0.50/docs/man/memcached_set_by_key.3 +132 -0
  158. data/ext/libmemcached-0.50/docs/man/memcached_set_memory_allocators.3 +111 -0
  159. data/ext/libmemcached-0.50/docs/man/memcached_set_sasl_callbacks.3 +95 -0
  160. data/ext/libmemcached-0.50/docs/man/memcached_set_user_data.3 +79 -0
  161. data/ext/libmemcached-0.50/docs/man/memcached_stat.3 +116 -0
  162. data/ext/libmemcached-0.50/docs/man/memcached_stat_execute.3 +116 -0
  163. data/ext/libmemcached-0.50/docs/man/memcached_stat_get_keys.3 +116 -0
  164. data/ext/libmemcached-0.50/docs/man/memcached_stat_get_value.3 +116 -0
  165. data/ext/libmemcached-0.50/docs/man/memcached_stat_servername.3 +116 -0
  166. data/ext/libmemcached-0.50/docs/man/memcached_strerror.3 +69 -0
  167. data/ext/libmemcached-0.50/docs/man/memcached_verbosity.3 +66 -0
  168. data/ext/libmemcached-0.50/docs/man/memcached_version.3 +76 -0
  169. data/ext/libmemcached-0.50/docs/man/memcapable.1 +92 -0
  170. data/ext/libmemcached-0.50/docs/man/memcat.1 +71 -0
  171. data/ext/libmemcached-0.50/docs/man/memcp.1 +77 -0
  172. data/ext/libmemcached-0.50/docs/man/memdump.1 +66 -0
  173. data/ext/libmemcached-0.50/docs/man/memerror.1 +65 -0
  174. data/ext/libmemcached-0.50/docs/man/memflush.1 +73 -0
  175. data/ext/libmemcached-0.50/docs/man/memrm.1 +72 -0
  176. data/ext/libmemcached-0.50/docs/man/memslap.1 +59 -0
  177. data/ext/libmemcached-0.50/docs/man/memstat.1 +70 -0
  178. data/ext/libmemcached-0.50/example/include.am +24 -0
  179. data/ext/libmemcached-0.50/example/interface_v0.c +594 -0
  180. data/ext/libmemcached-0.50/example/interface_v1.c +411 -0
  181. data/ext/libmemcached-0.50/example/memcached_light.c +474 -0
  182. data/ext/libmemcached-0.50/example/memcached_light.h +7 -0
  183. data/ext/libmemcached-0.50/example/storage.c +172 -0
  184. data/ext/libmemcached-0.50/example/storage.h +27 -0
  185. data/ext/libmemcached-0.50/example/storage_innodb.c +535 -0
  186. data/ext/libmemcached-0.50/libhashkit/algorithm.cc +69 -0
  187. data/ext/libmemcached-0.50/libhashkit/algorithm.h +96 -0
  188. data/ext/libmemcached-0.50/libhashkit/behavior.cc +9 -0
  189. data/ext/libmemcached-0.50/libhashkit/behavior.h +26 -0
  190. data/ext/libmemcached-0.50/libhashkit/common.h +33 -0
  191. data/ext/libmemcached-0.50/libhashkit/configure.h.in +19 -0
  192. data/ext/libmemcached-0.50/libhashkit/crc32.cc +86 -0
  193. data/ext/libmemcached-0.50/libhashkit/digest.cc +62 -0
  194. data/ext/libmemcached-0.50/libhashkit/digest.h +30 -0
  195. data/ext/libmemcached-0.50/libhashkit/fnv.cc +75 -0
  196. data/ext/libmemcached-0.50/libhashkit/function.cc +156 -0
  197. data/ext/libmemcached-0.50/libhashkit/function.h +44 -0
  198. data/ext/libmemcached-0.50/libhashkit/hashkit.cc +100 -0
  199. data/ext/libmemcached-0.50/libhashkit/hashkit.h +95 -0
  200. data/ext/libmemcached-0.50/libhashkit/hashkit.hpp +97 -0
  201. data/ext/libmemcached-0.50/libhashkit/hsieh.cc +70 -0
  202. data/ext/libmemcached-0.50/libhashkit/include.am +69 -0
  203. data/ext/libmemcached-0.50/libhashkit/jenkins.cc +214 -0
  204. data/ext/libmemcached-0.50/libhashkit/ketama.cc +164 -0
  205. data/ext/libmemcached-0.50/libhashkit/md5.cc +367 -0
  206. data/ext/libmemcached-0.50/libhashkit/murmur.cc +77 -0
  207. data/ext/libmemcached-0.50/libhashkit/one_at_a_time.cc +34 -0
  208. data/ext/libmemcached-0.50/libhashkit/str_algorithm.cc +58 -0
  209. data/ext/libmemcached-0.50/libhashkit/str_algorithm.h +48 -0
  210. data/ext/libmemcached-0.50/libhashkit/strerror.cc +25 -0
  211. data/ext/libmemcached-0.50/libhashkit/strerror.h +23 -0
  212. data/ext/libmemcached-0.50/libhashkit/types.h +90 -0
  213. data/ext/libmemcached-0.50/libhashkit/visibility.h +48 -0
  214. data/ext/libmemcached-0.50/libmemcached/allocators.cc +119 -0
  215. data/ext/libmemcached-0.50/libmemcached/allocators.h +87 -0
  216. data/ext/libmemcached-0.50/libmemcached/analyze.cc +110 -0
  217. data/ext/libmemcached-0.50/libmemcached/analyze.h +66 -0
  218. data/ext/libmemcached-0.50/libmemcached/array.c +128 -0
  219. data/ext/libmemcached-0.50/libmemcached/array.h +75 -0
  220. data/ext/libmemcached-0.50/libmemcached/auto.cc +383 -0
  221. data/ext/libmemcached-0.50/libmemcached/auto.h +111 -0
  222. data/ext/libmemcached-0.50/libmemcached/basic_string.h +55 -0
  223. data/ext/libmemcached-0.50/libmemcached/behavior.cc +590 -0
  224. data/ext/libmemcached-0.50/libmemcached/behavior.h +86 -0
  225. data/ext/libmemcached-0.50/libmemcached/byteorder.cc +90 -0
  226. data/ext/libmemcached-0.50/libmemcached/byteorder.h +52 -0
  227. data/ext/libmemcached-0.50/libmemcached/callback.cc +160 -0
  228. data/ext/libmemcached-0.50/libmemcached/callback.h +61 -0
  229. data/ext/libmemcached-0.50/libmemcached/common.h +182 -0
  230. data/ext/libmemcached-0.50/libmemcached/configure.h.in +52 -0
  231. data/ext/libmemcached-0.50/libmemcached/connect.cc +626 -0
  232. data/ext/libmemcached-0.50/libmemcached/constants.h +167 -0
  233. data/ext/libmemcached-0.50/libmemcached/delete.cc +266 -0
  234. data/ext/libmemcached-0.50/libmemcached/delete.h +57 -0
  235. data/ext/libmemcached-0.50/libmemcached/do.cc +100 -0
  236. data/ext/libmemcached-0.50/libmemcached/do.hpp +49 -0
  237. data/ext/libmemcached-0.50/libmemcached/dump.cc +107 -0
  238. data/ext/libmemcached-0.50/libmemcached/dump.h +51 -0
  239. data/ext/libmemcached-0.50/libmemcached/error.cc +419 -0
  240. data/ext/libmemcached-0.50/libmemcached/error.h +61 -0
  241. data/ext/libmemcached-0.50/libmemcached/error.hpp +87 -0
  242. data/ext/libmemcached-0.50/libmemcached/exception.hpp +63 -0
  243. data/ext/libmemcached-0.50/libmemcached/fetch.cc +267 -0
  244. data/ext/libmemcached-0.50/libmemcached/fetch.h +53 -0
  245. data/ext/libmemcached-0.50/libmemcached/flush.cc +149 -0
  246. data/ext/libmemcached-0.50/libmemcached/flush.h +49 -0
  247. data/ext/libmemcached-0.50/libmemcached/flush_buffers.cc +66 -0
  248. data/ext/libmemcached-0.50/libmemcached/flush_buffers.h +49 -0
  249. data/ext/libmemcached-0.50/libmemcached/get.cc +842 -0
  250. data/ext/libmemcached-0.50/libmemcached/get.h +135 -0
  251. data/ext/libmemcached-0.50/libmemcached/hash.cc +178 -0
  252. data/ext/libmemcached-0.50/libmemcached/hash.h +68 -0
  253. data/ext/libmemcached-0.50/libmemcached/hosts.cc +516 -0
  254. data/ext/libmemcached-0.50/libmemcached/include.am +183 -0
  255. data/ext/libmemcached-0.50/libmemcached/initialize_query.cc +70 -0
  256. data/ext/libmemcached-0.50/libmemcached/initialize_query.h +51 -0
  257. data/ext/libmemcached-0.50/libmemcached/internal.h +46 -0
  258. data/ext/libmemcached-0.50/libmemcached/io.cc +920 -0
  259. data/ext/libmemcached-0.50/libmemcached/io.h +119 -0
  260. data/ext/libmemcached-0.50/libmemcached/is.h +48 -0
  261. data/ext/libmemcached-0.50/libmemcached/key.cc +23 -0
  262. data/ext/libmemcached-0.50/libmemcached/libmemcached_probes.d +30 -0
  263. data/ext/libmemcached-0.50/libmemcached/libmemcached_probes.h +118 -0
  264. data/ext/libmemcached-0.50/libmemcached/memcached.cc +437 -0
  265. data/ext/libmemcached-0.50/libmemcached/memcached.h +214 -0
  266. data/ext/libmemcached-0.50/libmemcached/memcached.hpp +799 -0
  267. data/ext/libmemcached-0.50/libmemcached/memcached/README.txt +7 -0
  268. data/ext/libmemcached-0.50/libmemcached/memcached/protocol_binary.h +726 -0
  269. data/ext/libmemcached-0.50/libmemcached/memcached/vbucket.h +26 -0
  270. data/ext/libmemcached-0.50/libmemcached/memcached_util.h +44 -0
  271. data/ext/libmemcached-0.50/libmemcached/memory.h +79 -0
  272. data/ext/libmemcached-0.50/libmemcached/options.cc +178 -0
  273. data/ext/libmemcached-0.50/libmemcached/options.h +49 -0
  274. data/ext/libmemcached-0.50/libmemcached/options.hpp +56 -0
  275. data/ext/libmemcached-0.50/libmemcached/options/context.h +151 -0
  276. data/ext/libmemcached-0.50/libmemcached/options/include.am +19 -0
  277. data/ext/libmemcached-0.50/libmemcached/options/parser.am +0 -0
  278. data/ext/libmemcached-0.50/libmemcached/options/parser.cc +2324 -0
  279. data/ext/libmemcached-0.50/libmemcached/options/parser.h +122 -0
  280. data/ext/libmemcached-0.50/libmemcached/options/scanner.cc +3203 -0
  281. data/ext/libmemcached-0.50/libmemcached/options/scanner.h +479 -0
  282. data/ext/libmemcached-0.50/libmemcached/options/server.h +60 -0
  283. data/ext/libmemcached-0.50/libmemcached/options/symbol.h +57 -0
  284. data/ext/libmemcached-0.50/libmemcached/parse.cc +110 -0
  285. data/ext/libmemcached-0.50/libmemcached/parse.h +23 -0
  286. data/ext/libmemcached-0.50/libmemcached/platform.h +56 -0
  287. data/ext/libmemcached-0.50/libmemcached/prefix_key.cc +65 -0
  288. data/ext/libmemcached-0.50/libmemcached/prefix_key.h +49 -0
  289. data/ext/libmemcached-0.50/libmemcached/protocol/ascii_handler.c +963 -0
  290. data/ext/libmemcached-0.50/libmemcached/protocol/ascii_handler.h +40 -0
  291. data/ext/libmemcached-0.50/libmemcached/protocol/binary_handler.c +1121 -0
  292. data/ext/libmemcached-0.50/libmemcached/protocol/binary_handler.h +47 -0
  293. data/ext/libmemcached-0.50/libmemcached/protocol/cache.c +149 -0
  294. data/ext/libmemcached-0.50/libmemcached/protocol/cache.h +116 -0
  295. data/ext/libmemcached-0.50/libmemcached/protocol/callback.h +418 -0
  296. data/ext/libmemcached-0.50/libmemcached/protocol/common.h +163 -0
  297. data/ext/libmemcached-0.50/libmemcached/protocol/include.am +26 -0
  298. data/ext/libmemcached-0.50/libmemcached/protocol/pedantic.c +202 -0
  299. data/ext/libmemcached-0.50/libmemcached/protocol/protocol_handler.c +365 -0
  300. data/ext/libmemcached-0.50/libmemcached/protocol_handler.h +215 -0
  301. data/ext/libmemcached-0.50/libmemcached/purge.cc +90 -0
  302. data/ext/libmemcached-0.50/libmemcached/quit.cc +139 -0
  303. data/ext/libmemcached-0.50/libmemcached/quit.h +55 -0
  304. data/ext/libmemcached-0.50/libmemcached/response.cc +619 -0
  305. data/ext/libmemcached-0.50/libmemcached/response.h +57 -0
  306. data/ext/libmemcached-0.50/libmemcached/result.cc +173 -0
  307. data/ext/libmemcached-0.50/libmemcached/result.h +100 -0
  308. data/ext/libmemcached-0.50/libmemcached/return.h +98 -0
  309. data/ext/libmemcached-0.50/libmemcached/sasl.c +408 -0
  310. data/ext/libmemcached-0.50/libmemcached/sasl.h +86 -0
  311. data/ext/libmemcached-0.50/libmemcached/server.cc +351 -0
  312. data/ext/libmemcached-0.50/libmemcached/server.h +169 -0
  313. data/ext/libmemcached-0.50/libmemcached/server_list.cc +88 -0
  314. data/ext/libmemcached-0.50/libmemcached/server_list.h +77 -0
  315. data/ext/libmemcached-0.50/libmemcached/stats.cc +623 -0
  316. data/ext/libmemcached-0.50/libmemcached/stats.h +96 -0
  317. data/ext/libmemcached-0.50/libmemcached/storage.cc +567 -0
  318. data/ext/libmemcached-0.50/libmemcached/storage.h +133 -0
  319. data/ext/libmemcached-0.50/libmemcached/strerror.cc +189 -0
  320. data/ext/libmemcached-0.50/libmemcached/strerror.h +50 -0
  321. data/ext/libmemcached-0.50/libmemcached/string.cc +253 -0
  322. data/ext/libmemcached-0.50/libmemcached/string.h +121 -0
  323. data/ext/libmemcached-0.50/libmemcached/touch.cc +106 -0
  324. data/ext/libmemcached-0.50/libmemcached/touch.h +59 -0
  325. data/ext/libmemcached-0.50/libmemcached/types.h +117 -0
  326. data/ext/libmemcached-0.50/libmemcached/util.h +40 -0
  327. data/ext/libmemcached-0.50/libmemcached/util/flush.cc +61 -0
  328. data/ext/libmemcached-0.50/libmemcached/util/flush.h +50 -0
  329. data/ext/libmemcached-0.50/libmemcached/util/include.am +34 -0
  330. data/ext/libmemcached-0.50/libmemcached/util/ping.cc +62 -0
  331. data/ext/libmemcached-0.50/libmemcached/util/ping.h +49 -0
  332. data/ext/libmemcached-0.50/libmemcached/util/pool.cc +392 -0
  333. data/ext/libmemcached-0.50/libmemcached/util/pool.h +78 -0
  334. data/ext/libmemcached-0.50/libmemcached/util/version.cc +87 -0
  335. data/ext/libmemcached-0.50/libmemcached/util/version.h +53 -0
  336. data/ext/libmemcached-0.50/libmemcached/verbosity.cc +97 -0
  337. data/ext/libmemcached-0.50/libmemcached/verbosity.h +50 -0
  338. data/ext/libmemcached-0.50/libmemcached/version.cc +214 -0
  339. data/ext/libmemcached-0.50/libmemcached/version.h +52 -0
  340. data/ext/libmemcached-0.50/libmemcached/virtual_bucket.c +118 -0
  341. data/ext/libmemcached-0.50/libmemcached/virtual_bucket.h +59 -0
  342. data/ext/libmemcached-0.50/libmemcached/visibility.h +51 -0
  343. data/ext/libmemcached-0.50/libmemcached/watchpoint.h +110 -0
  344. data/ext/libmemcached-0.50/libtest/callbacks.h +21 -0
  345. data/ext/libmemcached-0.50/libtest/collection.h +19 -0
  346. data/ext/libmemcached-0.50/libtest/common.h +50 -0
  347. data/ext/libmemcached-0.50/libtest/core.h +11 -0
  348. data/ext/libmemcached-0.50/libtest/error.h +18 -0
  349. data/ext/libmemcached-0.50/libtest/failed.h +52 -0
  350. data/ext/libmemcached-0.50/libtest/framework.cc +57 -0
  351. data/ext/libmemcached-0.50/libtest/framework.h +137 -0
  352. data/ext/libmemcached-0.50/libtest/get.h +22 -0
  353. data/ext/libmemcached-0.50/libtest/include.am +52 -0
  354. data/ext/libmemcached-0.50/libtest/runner.h +19 -0
  355. data/ext/libmemcached-0.50/libtest/server.c +355 -0
  356. data/ext/libmemcached-0.50/libtest/server.h +43 -0
  357. data/ext/libmemcached-0.50/libtest/stats.h +30 -0
  358. data/ext/libmemcached-0.50/libtest/strerror.h +14 -0
  359. data/ext/libmemcached-0.50/libtest/test.cc +319 -0
  360. data/ext/libmemcached-0.50/libtest/test.h +162 -0
  361. data/ext/libmemcached-0.50/libtest/test.hpp +46 -0
  362. data/ext/libmemcached-0.50/libtest/visibility.h +69 -0
  363. data/ext/libmemcached-0.50/m4/ac_cxx_header_stdcxx_98.m4 +83 -0
  364. data/ext/libmemcached-0.50/m4/acx_pthread.m4 +271 -0
  365. data/ext/libmemcached-0.50/m4/byteorder.m4 +19 -0
  366. data/ext/libmemcached-0.50/m4/deprecated.m4 +17 -0
  367. data/ext/libmemcached-0.50/m4/eagain.m4 +28 -0
  368. data/ext/libmemcached-0.50/m4/enable_utillib.m4 +16 -0
  369. data/ext/libmemcached-0.50/m4/gettext.m4 +379 -0
  370. data/ext/libmemcached-0.50/m4/hsieh.m4 +18 -0
  371. data/ext/libmemcached-0.50/m4/iconv.m4 +214 -0
  372. data/ext/libmemcached-0.50/m4/lib-ld.m4 +110 -0
  373. data/ext/libmemcached-0.50/m4/lib-link.m4 +767 -0
  374. data/ext/libmemcached-0.50/m4/lib-prefix.m4 +221 -0
  375. data/ext/libmemcached-0.50/m4/libtool.m4 +7851 -0
  376. data/ext/libmemcached-0.50/m4/ltoptions.m4 +369 -0
  377. data/ext/libmemcached-0.50/m4/ltsugar.m4 +123 -0
  378. data/ext/libmemcached-0.50/m4/ltversion.m4 +23 -0
  379. data/ext/libmemcached-0.50/m4/lt~obsolete.m4 +98 -0
  380. data/ext/libmemcached-0.50/m4/memaslap.m4 +9 -0
  381. data/ext/libmemcached-0.50/m4/memcached.m4 +31 -0
  382. data/ext/libmemcached-0.50/m4/murmur.m4 +18 -0
  383. data/ext/libmemcached-0.50/m4/pandora_64bit.m4 +60 -0
  384. data/ext/libmemcached-0.50/m4/pandora_bison.m4 +33 -0
  385. data/ext/libmemcached-0.50/m4/pandora_canonical.m4 +418 -0
  386. data/ext/libmemcached-0.50/m4/pandora_check_compiler_version.m4 +37 -0
  387. data/ext/libmemcached-0.50/m4/pandora_check_cxx_standard.m4 +23 -0
  388. data/ext/libmemcached-0.50/m4/pandora_cinttypes.m4 +39 -0
  389. data/ext/libmemcached-0.50/m4/pandora_clock_gettime.m4 +15 -0
  390. data/ext/libmemcached-0.50/m4/pandora_compile_stdcxx_0x.m4 +103 -0
  391. data/ext/libmemcached-0.50/m4/pandora_cstdint.m4 +38 -0
  392. data/ext/libmemcached-0.50/m4/pandora_cxx_demangle.m4 +27 -0
  393. data/ext/libmemcached-0.50/m4/pandora_enable_dtrace.m4 +60 -0
  394. data/ext/libmemcached-0.50/m4/pandora_ensure_gcc_version.m4 +62 -0
  395. data/ext/libmemcached-0.50/m4/pandora_extensions.m4 +16 -0
  396. data/ext/libmemcached-0.50/m4/pandora_fdatasync.m4 +25 -0
  397. data/ext/libmemcached-0.50/m4/pandora_flex.m4 +33 -0
  398. data/ext/libmemcached-0.50/m4/pandora_have_better_malloc.m4 +66 -0
  399. data/ext/libmemcached-0.50/m4/pandora_have_boost.m4 +93 -0
  400. data/ext/libmemcached-0.50/m4/pandora_have_gcc_atomics.m4 +37 -0
  401. data/ext/libmemcached-0.50/m4/pandora_have_innodb.m4 +41 -0
  402. data/ext/libmemcached-0.50/m4/pandora_have_libaio.m4 +56 -0
  403. data/ext/libmemcached-0.50/m4/pandora_have_libavahi.m4 +41 -0
  404. data/ext/libmemcached-0.50/m4/pandora_have_libbdb.m4 +40 -0
  405. data/ext/libmemcached-0.50/m4/pandora_have_libboost_date_time.m4 +46 -0
  406. data/ext/libmemcached-0.50/m4/pandora_have_libboost_filesystem.m4 +47 -0
  407. data/ext/libmemcached-0.50/m4/pandora_have_libboost_iostreams.m4 +49 -0
  408. data/ext/libmemcached-0.50/m4/pandora_have_libboost_options.m4 +47 -0
  409. data/ext/libmemcached-0.50/m4/pandora_have_libboost_regex.m4 +54 -0
  410. data/ext/libmemcached-0.50/m4/pandora_have_libboost_test.m4 +45 -0
  411. data/ext/libmemcached-0.50/m4/pandora_have_libboost_thread.m4 +54 -0
  412. data/ext/libmemcached-0.50/m4/pandora_have_libcassandra.m4 +44 -0
  413. data/ext/libmemcached-0.50/m4/pandora_have_libcurl.m4 +62 -0
  414. data/ext/libmemcached-0.50/m4/pandora_have_libdl.m4 +51 -0
  415. data/ext/libmemcached-0.50/m4/pandora_have_libdrizzle.m4 +61 -0
  416. data/ext/libmemcached-0.50/m4/pandora_have_libevent.m4 +66 -0
  417. data/ext/libmemcached-0.50/m4/pandora_have_libgearman.m4 +41 -0
  418. data/ext/libmemcached-0.50/m4/pandora_have_libgtest.m4 +47 -0
  419. data/ext/libmemcached-0.50/m4/pandora_have_libhaildb.m4 +43 -0
  420. data/ext/libmemcached-0.50/m4/pandora_have_libhashkit.m4 +42 -0
  421. data/ext/libmemcached-0.50/m4/pandora_have_libinnodb.m4 +64 -0
  422. data/ext/libmemcached-0.50/m4/pandora_have_libldap.m4 +73 -0
  423. data/ext/libmemcached-0.50/m4/pandora_have_libmemcached.m4 +106 -0
  424. data/ext/libmemcached-0.50/m4/pandora_have_libmysqlclient.m4 +146 -0
  425. data/ext/libmemcached-0.50/m4/pandora_have_libndbclient.m4 +80 -0
  426. data/ext/libmemcached-0.50/m4/pandora_have_libpcre.m4 +73 -0
  427. data/ext/libmemcached-0.50/m4/pandora_have_libpq.m4 +46 -0
  428. data/ext/libmemcached-0.50/m4/pandora_have_libpqxx.m4 +44 -0
  429. data/ext/libmemcached-0.50/m4/pandora_have_libsqlite3.m4 +42 -0
  430. data/ext/libmemcached-0.50/m4/pandora_have_libtokyocabinet.m4 +54 -0
  431. data/ext/libmemcached-0.50/m4/pandora_have_libuuid.m4 +55 -0
  432. data/ext/libmemcached-0.50/m4/pandora_have_libvbucket.m4 +40 -0
  433. data/ext/libmemcached-0.50/m4/pandora_have_libxml2.m4 +52 -0
  434. data/ext/libmemcached-0.50/m4/pandora_have_libz.m4 +51 -0
  435. data/ext/libmemcached-0.50/m4/pandora_have_protobuf.m4 +82 -0
  436. data/ext/libmemcached-0.50/m4/pandora_have_sasl.m4 +133 -0
  437. data/ext/libmemcached-0.50/m4/pandora_have_thrift.m4 +45 -0
  438. data/ext/libmemcached-0.50/m4/pandora_header_assert.m4 +23 -0
  439. data/ext/libmemcached-0.50/m4/pandora_header_stdcxx_98.m4 +83 -0
  440. data/ext/libmemcached-0.50/m4/pandora_intltool.m4 +225 -0
  441. data/ext/libmemcached-0.50/m4/pandora_libtool.m4 +25 -0
  442. data/ext/libmemcached-0.50/m4/pandora_optimize.m4 +75 -0
  443. data/ext/libmemcached-0.50/m4/pandora_platform.m4 +117 -0
  444. data/ext/libmemcached-0.50/m4/pandora_plugins.m4 +62 -0
  445. data/ext/libmemcached-0.50/m4/pandora_print_callstack.m4 +61 -0
  446. data/ext/libmemcached-0.50/m4/pandora_pthread.m4 +258 -0
  447. data/ext/libmemcached-0.50/m4/pandora_python3_devel.m4 +236 -0
  448. data/ext/libmemcached-0.50/m4/pandora_run_cpplint.m4 +8 -0
  449. data/ext/libmemcached-0.50/m4/pandora_sasl.m4 +133 -0
  450. data/ext/libmemcached-0.50/m4/pandora_shared_ptr.m4 +59 -0
  451. data/ext/libmemcached-0.50/m4/pandora_stack_direction.m4 +39 -0
  452. data/ext/libmemcached-0.50/m4/pandora_stl_hash.m4 +94 -0
  453. data/ext/libmemcached-0.50/m4/pandora_swig.m4 +39 -0
  454. data/ext/libmemcached-0.50/m4/pandora_use_pipe.m4 +36 -0
  455. data/ext/libmemcached-0.50/m4/pandora_vc_build.m4 +168 -0
  456. data/ext/libmemcached-0.50/m4/pandora_version.m4 +11 -0
  457. data/ext/libmemcached-0.50/m4/pandora_visibility.m4 +75 -0
  458. data/ext/libmemcached-0.50/m4/pandora_warnings.m4 +447 -0
  459. data/ext/libmemcached-0.50/m4/pandora_with_gettext.m4 +44 -0
  460. data/ext/libmemcached-0.50/m4/pandora_with_lua.m4 +55 -0
  461. data/ext/libmemcached-0.50/m4/pandora_with_memcached.m4 +41 -0
  462. data/ext/libmemcached-0.50/m4/pandora_with_perl.m4 +81 -0
  463. data/ext/libmemcached-0.50/m4/pandora_with_php.m4 +56 -0
  464. data/ext/libmemcached-0.50/m4/pandora_with_python.m4 +37 -0
  465. data/ext/libmemcached-0.50/m4/pandora_with_python3.m4 +44 -0
  466. data/ext/libmemcached-0.50/m4/pandora_with_r.m4 +33 -0
  467. data/ext/libmemcached-0.50/m4/pandora_with_ruby.m4 +79 -0
  468. data/ext/libmemcached-0.50/m4/pandora_with_valgrind.m4 +17 -0
  469. data/ext/libmemcached-0.50/m4/pkg.m4 +157 -0
  470. data/ext/libmemcached-0.50/m4/po.m4 +449 -0
  471. data/ext/libmemcached-0.50/m4/progtest.m4 +92 -0
  472. data/ext/libmemcached-0.50/m4/protocol_binary.m4 +36 -0
  473. data/ext/libmemcached-0.50/m4/setsockopt.m4 +73 -0
  474. data/ext/libmemcached-0.50/m4/socket_send_flags.m4 +66 -0
  475. data/ext/libmemcached-0.50/poll/include.am +8 -0
  476. data/ext/libmemcached-0.50/poll/poll.c +77 -0
  477. data/ext/libmemcached-0.50/poll/poll.h +45 -0
  478. data/ext/libmemcached-0.50/support/include.am +11 -0
  479. data/ext/libmemcached-0.50/support/libmemcached-fc.spec.in +105 -0
  480. data/ext/libmemcached-0.50/support/libmemcached.pc.in +10 -0
  481. data/ext/libmemcached-0.50/support/libmemcached.spec.in +281 -0
  482. data/ext/libmemcached-0.50/support/set_benchmark.sh +5 -0
  483. data/ext/libmemcached-0.50/tests/atomsmasher.cc +295 -0
  484. data/ext/libmemcached-0.50/tests/basic.cc +134 -0
  485. data/ext/libmemcached-0.50/tests/basic.h +66 -0
  486. data/ext/libmemcached-0.50/tests/cpp_example.cc +195 -0
  487. data/ext/libmemcached-0.50/tests/deprecated.cc +72 -0
  488. data/ext/libmemcached-0.50/tests/deprecated.h +49 -0
  489. data/ext/libmemcached-0.50/tests/error_conditions.cc +63 -0
  490. data/ext/libmemcached-0.50/tests/error_conditions.h +48 -0
  491. data/ext/libmemcached-0.50/tests/hash_plus.cc +225 -0
  492. data/ext/libmemcached-0.50/tests/hash_results.h +127 -0
  493. data/ext/libmemcached-0.50/tests/hashkit_functions.cc +619 -0
  494. data/ext/libmemcached-0.50/tests/include.am +342 -0
  495. data/ext/libmemcached-0.50/tests/ketama_test_cases.h +121 -0
  496. data/ext/libmemcached-0.50/tests/ketama_test_cases_spy.h +118 -0
  497. data/ext/libmemcached-0.50/tests/libmemcached_world.h +205 -0
  498. data/ext/libmemcached-0.50/tests/mem_functions.cc +6648 -0
  499. data/ext/libmemcached-0.50/tests/mem_udp.cc +510 -0
  500. data/ext/libmemcached-0.50/tests/output_plus.res +5 -0
  501. data/ext/libmemcached-0.50/tests/parser.cc +599 -0
  502. data/ext/libmemcached-0.50/tests/parser.h +109 -0
  503. data/ext/libmemcached-0.50/tests/plus.cpp +240 -0
  504. data/ext/libmemcached-0.50/tests/pool.cc +78 -0
  505. data/ext/libmemcached-0.50/tests/pool.h +49 -0
  506. data/ext/libmemcached-0.50/tests/print.cc +58 -0
  507. data/ext/libmemcached-0.50/tests/print.h +51 -0
  508. data/ext/libmemcached-0.50/tests/replication.cc +333 -0
  509. data/ext/libmemcached-0.50/tests/replication.h +64 -0
  510. data/ext/libmemcached-0.50/tests/start.cc +29 -0
  511. data/ext/libmemcached-0.50/tests/string.cc +174 -0
  512. data/ext/libmemcached-0.50/tests/string.h +67 -0
  513. data/ext/libmemcached-0.50/tests/virtual_buckets.cc +143 -0
  514. data/ext/libmemcached-0.50/tests/virtual_buckets.h +51 -0
  515. data/ext/libmemcached-0.50/win32/include.am +11 -0
  516. data/ext/libmemcached-0.50/win32/wrappers.h +55 -0
  517. data/ext/rlibmemcached.i +263 -0
  518. data/ext/rlibmemcached_wrap.c +16732 -0
  519. data/lib/memcached.rb +32 -0
  520. data/lib/memcached/auth.rb +16 -0
  521. data/lib/memcached/behaviors.rb +77 -0
  522. data/lib/memcached/exceptions.rb +84 -0
  523. data/lib/memcached/experimental.rb +48 -0
  524. data/lib/memcached/memcached.rb +660 -0
  525. data/lib/memcached/rails.rb +133 -0
  526. data/test/profile/benchmark.rb +245 -0
  527. data/test/profile/c_profiler.rb +14 -0
  528. data/test/profile/exercise.rb +185 -0
  529. data/test/profile/rb_profiler.rb +21 -0
  530. data/test/profile/valgrind.rb +10 -0
  531. data/test/setup.rb +30 -0
  532. data/test/teardown.rb +0 -0
  533. data/test/test_helper.rb +19 -0
  534. data/test/unit/binding_test.rb +8 -0
  535. data/test/unit/memcached_experimental_test.rb +274 -0
  536. data/test/unit/memcached_test.rb +1293 -0
  537. data/test/unit/rails_test.rb +122 -0
  538. metadata +650 -0
  539. metadata.gz.sig +0 -0
@@ -0,0 +1,2094 @@
1
+ /* LibMemcached
2
+ * Copyright (C) 2006-2009 Brian Aker
3
+ * All rights reserved.
4
+ *
5
+ * Use and distribution licensed under the BSD license. See
6
+ * the COPYING file in the parent directory for full text.
7
+ *
8
+ * Summary:
9
+ *
10
+ */
11
+
12
+ /* -*- Mode: C; tab-width: 2; c-basic-offset: 2; indent-tabs-mode: nil -*- */
13
+ #undef NDEBUG
14
+
15
+ #include "config.h"
16
+ #include <pthread.h>
17
+ #include <sys/types.h>
18
+ #include <fcntl.h>
19
+ #include <signal.h>
20
+ #include <stdio.h>
21
+ #include <stdlib.h>
22
+ #include <errno.h>
23
+ #include <assert.h>
24
+ #include <string.h>
25
+ #include <inttypes.h>
26
+ #include <stdbool.h>
27
+ #include <unistd.h>
28
+ #include <ctype.h>
29
+
30
+ #include <libmemcached/memcached.h>
31
+ #include <libmemcached/memcached/protocol_binary.h>
32
+ #include <libmemcached/byteorder.h>
33
+ #include "utilities.h"
34
+
35
+ #ifdef linux
36
+ /* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to
37
+ * optimize the conversion functions, but the prototypes generate warnings
38
+ * from gcc. The conversion methods isn't the bottleneck for my app, so
39
+ * just remove the warnings by undef'ing the optimization ..
40
+ */
41
+ #undef ntohs
42
+ #undef ntohl
43
+ #endif
44
+
45
+ /* Should we generate coredumps when we enounter an error (-c) */
46
+ static bool do_core= false;
47
+ /* connection to the server */
48
+ static memcached_socket_t sock;
49
+ /* Should the output from test failures be verbose or quiet? */
50
+ static bool verbose= false;
51
+
52
+ /* The number of seconds to wait for an IO-operation */
53
+ static int timeout= 2;
54
+
55
+ /*
56
+ * Instead of having to cast between the different datatypes we create
57
+ * a union of all of the different types of pacages we want to send.
58
+ * A lot of the different commands use the same packet layout, so I'll
59
+ * just define the different types I need. The typedefs only contain
60
+ * the header of the message, so we need some space for keys and body
61
+ * To avoid to have to do multiple writes, lets add a chunk of memory
62
+ * to use. 1k should be more than enough for header, key and body.
63
+ */
64
+ typedef union
65
+ {
66
+ protocol_binary_request_no_extras plain;
67
+ protocol_binary_request_flush flush;
68
+ protocol_binary_request_incr incr;
69
+ protocol_binary_request_set set;
70
+ char bytes[1024];
71
+ } command;
72
+
73
+ typedef union
74
+ {
75
+ protocol_binary_response_no_extras plain;
76
+ protocol_binary_response_incr incr;
77
+ protocol_binary_response_decr decr;
78
+ char bytes[1024];
79
+ } response;
80
+
81
+ enum test_return
82
+ {
83
+ TEST_SKIP, TEST_PASS, TEST_PASS_RECONNECT, TEST_FAIL
84
+ };
85
+
86
+ /**
87
+ * Try to get an addrinfo struct for a given port on a given host
88
+ */
89
+ static struct addrinfo *lookuphost(const char *hostname, const char *port)
90
+ {
91
+ struct addrinfo *ai= 0;
92
+ struct addrinfo hints;
93
+ memset(&hints, 0, sizeof(struct addrinfo));
94
+ hints.ai_family=AF_UNSPEC;
95
+ hints.ai_protocol=IPPROTO_TCP;
96
+ hints.ai_socktype=SOCK_STREAM;
97
+
98
+ int error= getaddrinfo(hostname, port, &hints, &ai);
99
+ if (error != 0)
100
+ {
101
+ if (error != EAI_SYSTEM)
102
+ fprintf(stderr, "getaddrinfo(): %s\n", gai_strerror(error));
103
+ else
104
+ perror("getaddrinfo()");
105
+ }
106
+
107
+ return ai;
108
+ }
109
+
110
+ /**
111
+ * Set the socket in nonblocking mode
112
+ * @return -1 if failure, the socket otherwise
113
+ */
114
+ static memcached_socket_t set_noblock(void)
115
+ {
116
+ #ifdef WIN32
117
+ u_long arg = 1;
118
+ if (ioctlsocket(sock, FIONBIO, &arg) == SOCKET_ERROR)
119
+ {
120
+ perror("Failed to set nonblocking io");
121
+ closesocket(sock);
122
+ return INVALID_SOCKET;
123
+ }
124
+ #else
125
+ int flags= fcntl(sock, F_GETFL, 0);
126
+ if (flags == -1)
127
+ {
128
+ perror("Failed to get socket flags");
129
+ closesocket(sock);
130
+ return INVALID_SOCKET;
131
+ }
132
+
133
+ if ((flags & O_NONBLOCK) != O_NONBLOCK)
134
+ {
135
+ if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
136
+ {
137
+ perror("Failed to set socket to nonblocking mode");
138
+ closesocket(sock);
139
+ return INVALID_SOCKET;
140
+ }
141
+ }
142
+ #endif
143
+ return sock;
144
+ }
145
+
146
+ /**
147
+ * Try to open a connection to the server
148
+ * @param hostname the name of the server to connect to
149
+ * @param port the port number (or service) to connect to
150
+ * @return positive integer if success, -1 otherwise
151
+ */
152
+ static memcached_socket_t connect_server(const char *hostname, const char *port)
153
+ {
154
+ struct addrinfo *ai= lookuphost(hostname, port);
155
+ sock= INVALID_SOCKET;
156
+ if (ai != NULL)
157
+ {
158
+ if ((sock= socket(ai->ai_family, ai->ai_socktype,
159
+ ai->ai_protocol)) != INVALID_SOCKET)
160
+ {
161
+ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == SOCKET_ERROR)
162
+ {
163
+ fprintf(stderr, "Failed to connect socket: %s\n",
164
+ strerror(get_socket_errno()));
165
+ closesocket(sock);
166
+ sock= INVALID_SOCKET;
167
+ }
168
+ else
169
+ {
170
+ sock= set_noblock();
171
+ }
172
+ }
173
+ else
174
+ fprintf(stderr, "Failed to create socket: %s\n",
175
+ strerror(get_socket_errno()));
176
+
177
+ freeaddrinfo(ai);
178
+ }
179
+
180
+ return sock;
181
+ }
182
+
183
+ static ssize_t timeout_io_op(memcached_socket_t fd, short direction, void *buf, size_t len)
184
+ {
185
+ ssize_t ret;
186
+
187
+ if (direction == POLLOUT)
188
+ {
189
+ ret= send(fd, buf, len, 0);
190
+ }
191
+ else
192
+ {
193
+ ret= recv(fd, buf, len, 0);
194
+ }
195
+
196
+ if (ret == SOCKET_ERROR && get_socket_errno() == EWOULDBLOCK)
197
+ {
198
+ struct pollfd fds;
199
+ memset(&fds, 0, sizeof(struct pollfd));
200
+ fds.events= direction;
201
+ fds.fd= fd;
202
+
203
+ int err= poll(&fds, 1, timeout * 1000);
204
+ if (err == 1)
205
+ {
206
+ if (direction == POLLOUT)
207
+ {
208
+ ret= send(fd, buf, len, 0);
209
+ }
210
+ else
211
+ {
212
+ ret= recv(fd, buf, len, 0);
213
+ }
214
+ }
215
+ else if (err == 0)
216
+ {
217
+ errno= ETIMEDOUT;
218
+ }
219
+ else
220
+ {
221
+ perror("Failed to poll");
222
+ return -1;
223
+ }
224
+ }
225
+
226
+ return ret;
227
+ }
228
+
229
+ /**
230
+ * Ensure that an expression is true. If it isn't print out a message similar
231
+ * to assert() and create a coredump if the user wants that. If not an error
232
+ * message is returned.
233
+ *
234
+ */
235
+ static enum test_return ensure(bool val, const char *expression, const char *file, int line)
236
+ {
237
+ if (!val)
238
+ {
239
+ if (verbose)
240
+ fprintf(stderr, "\n%s:%d: %s", file, line, expression);
241
+
242
+ if (do_core)
243
+ abort();
244
+
245
+ return TEST_FAIL;
246
+ }
247
+
248
+ return TEST_PASS;
249
+ }
250
+
251
+ #define verify(expression) do { if (ensure(expression, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
252
+ #define execute(expression) do { if (ensure(expression == TEST_PASS, #expression, __FILE__, __LINE__) == TEST_FAIL) return TEST_FAIL; } while (0)
253
+
254
+ /**
255
+ * Send a chunk of memory over the socket (retry if the call is iterrupted
256
+ */
257
+ static enum test_return retry_write(const void* buf, size_t len)
258
+ {
259
+ size_t offset= 0;
260
+ const char* ptr= static_cast<const char *>(buf);
261
+
262
+ do
263
+ {
264
+ size_t num_bytes= len - offset;
265
+ ssize_t nw= timeout_io_op(sock, POLLOUT, (void*)(ptr + offset), num_bytes);
266
+ if (nw == -1)
267
+ verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
268
+ else
269
+ offset+= (size_t)nw;
270
+ } while (offset < len);
271
+
272
+ return TEST_PASS;
273
+ }
274
+
275
+ /**
276
+ * Resend a packet to the server (All fields in the command header should
277
+ * be in network byte order)
278
+ */
279
+ static enum test_return resend_packet(command *cmd)
280
+ {
281
+ size_t length= sizeof (protocol_binary_request_no_extras) +
282
+ ntohl(cmd->plain.message.header.request.bodylen);
283
+
284
+ execute(retry_write(cmd, length));
285
+ return TEST_PASS;
286
+ }
287
+
288
+ /**
289
+ * Send a command to the server. The command header needs to be updated
290
+ * to network byte order
291
+ */
292
+ static enum test_return send_packet(command *cmd)
293
+ {
294
+ /* Fix the byteorder of the header */
295
+ cmd->plain.message.header.request.keylen=
296
+ ntohs(cmd->plain.message.header.request.keylen);
297
+ cmd->plain.message.header.request.bodylen=
298
+ ntohl(cmd->plain.message.header.request.bodylen);
299
+ cmd->plain.message.header.request.cas=
300
+ memcached_ntohll(cmd->plain.message.header.request.cas);
301
+
302
+ execute(resend_packet(cmd));
303
+ return TEST_PASS;
304
+ }
305
+
306
+ /**
307
+ * Read a fixed length chunk of data from the server
308
+ */
309
+ static enum test_return retry_read(void *buf, size_t len)
310
+ {
311
+ size_t offset= 0;
312
+ do
313
+ {
314
+ ssize_t nr= timeout_io_op(sock, POLLIN, ((char*) buf) + offset, len - offset);
315
+ switch (nr) {
316
+ case -1 :
317
+ fprintf(stderr, "Errno: %d %s\n", get_socket_errno(), strerror(errno));
318
+ verify(get_socket_errno() == EINTR || get_socket_errno() == EAGAIN);
319
+ break;
320
+ case 0:
321
+ return TEST_FAIL;
322
+ default:
323
+ offset+= (size_t)nr;
324
+ }
325
+ } while (offset < len);
326
+
327
+ return TEST_PASS;
328
+ }
329
+
330
+ /**
331
+ * Receive a response from the server and conver the fields in the header
332
+ * to local byte order
333
+ */
334
+ static enum test_return recv_packet(response *rsp)
335
+ {
336
+ execute(retry_read(rsp, sizeof(protocol_binary_response_no_extras)));
337
+
338
+ /* Fix the byte order in the packet header */
339
+ rsp->plain.message.header.response.keylen=
340
+ ntohs(rsp->plain.message.header.response.keylen);
341
+ rsp->plain.message.header.response.status=
342
+ ntohs(rsp->plain.message.header.response.status);
343
+ rsp->plain.message.header.response.bodylen=
344
+ ntohl(rsp->plain.message.header.response.bodylen);
345
+ rsp->plain.message.header.response.cas=
346
+ memcached_ntohll(rsp->plain.message.header.response.cas);
347
+
348
+ size_t bodysz= rsp->plain.message.header.response.bodylen;
349
+ if (bodysz > 0)
350
+ execute(retry_read(rsp->bytes + sizeof (protocol_binary_response_no_extras), bodysz));
351
+
352
+ return TEST_PASS;
353
+ }
354
+
355
+ /**
356
+ * Create a storage command (add, set, replace etc)
357
+ *
358
+ * @param cmd destination buffer
359
+ * @param cc the storage command to create
360
+ * @param key the key to store
361
+ * @param keylen the length of the key
362
+ * @param dta the data to store with the key
363
+ * @param dtalen the length of the data to store with the key
364
+ * @param flags the flags to store along with the key
365
+ * @param exptime the expiry time for the key
366
+ */
367
+ static void storage_command(command *cmd,
368
+ uint8_t cc,
369
+ const void* key,
370
+ size_t keylen,
371
+ const void* dta,
372
+ size_t dtalen,
373
+ uint32_t flags,
374
+ uint32_t exptime)
375
+ {
376
+ /* all of the storage commands use the same command layout */
377
+ protocol_binary_request_set *request= &cmd->set;
378
+
379
+ memset(request, 0, sizeof (*request));
380
+ request->message.header.request.magic= PROTOCOL_BINARY_REQ;
381
+ request->message.header.request.opcode= cc;
382
+ request->message.header.request.keylen= (uint16_t)keylen;
383
+ request->message.header.request.extlen= 8;
384
+ request->message.header.request.bodylen= (uint32_t)(keylen + 8 + dtalen);
385
+ request->message.header.request.opaque= 0xdeadbeef;
386
+ request->message.body.flags= flags;
387
+ request->message.body.expiration= exptime;
388
+
389
+ off_t key_offset= sizeof (protocol_binary_request_no_extras) + 8;
390
+ memcpy(cmd->bytes + key_offset, key, keylen);
391
+ if (dta != NULL)
392
+ memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
393
+ }
394
+
395
+ /**
396
+ * Create a basic command to send to the server
397
+ * @param cmd destination buffer
398
+ * @param cc the command to create
399
+ * @param key the key to store
400
+ * @param keylen the length of the key
401
+ * @param dta the data to store with the key
402
+ * @param dtalen the length of the data to store with the key
403
+ */
404
+ static void raw_command(command *cmd,
405
+ uint8_t cc,
406
+ const void* key,
407
+ size_t keylen,
408
+ const void* dta,
409
+ size_t dtalen)
410
+ {
411
+ /* all of the storage commands use the same command layout */
412
+ memset(cmd, 0, sizeof (*cmd));
413
+ cmd->plain.message.header.request.magic= PROTOCOL_BINARY_REQ;
414
+ cmd->plain.message.header.request.opcode= cc;
415
+ cmd->plain.message.header.request.keylen= (uint16_t)keylen;
416
+ cmd->plain.message.header.request.bodylen= (uint32_t)(keylen + dtalen);
417
+ cmd->plain.message.header.request.opaque= 0xdeadbeef;
418
+
419
+ off_t key_offset= sizeof (protocol_binary_request_no_extras);
420
+
421
+ if (key != NULL)
422
+ memcpy(cmd->bytes + key_offset, key, keylen);
423
+
424
+ if (dta != NULL)
425
+ memcpy(cmd->bytes + key_offset + keylen, dta, dtalen);
426
+ }
427
+
428
+ /**
429
+ * Create the flush command
430
+ * @param cmd destination buffer
431
+ * @param cc the command to create (FLUSH/FLUSHQ)
432
+ * @param exptime when to flush
433
+ * @param use_extra to force using of the extra field?
434
+ */
435
+ static void flush_command(command *cmd,
436
+ uint8_t cc, uint32_t exptime, bool use_extra)
437
+ {
438
+ memset(cmd, 0, sizeof (cmd->flush));
439
+ cmd->flush.message.header.request.magic= PROTOCOL_BINARY_REQ;
440
+ cmd->flush.message.header.request.opcode= cc;
441
+ cmd->flush.message.header.request.opaque= 0xdeadbeef;
442
+
443
+ if (exptime != 0 || use_extra)
444
+ {
445
+ cmd->flush.message.header.request.extlen= 4;
446
+ cmd->flush.message.body.expiration= htonl(exptime);
447
+ cmd->flush.message.header.request.bodylen= 4;
448
+ }
449
+ }
450
+
451
+ /**
452
+ * Create a incr/decr command
453
+ * @param cc the cmd to create (FLUSH/FLUSHQ)
454
+ * @param key the key to operate on
455
+ * @param keylen the number of bytes in the key
456
+ * @param delta the number to add/subtract
457
+ * @param initial the initial value if the key doesn't exist
458
+ * @param exptime when the key should expire if it isn't set
459
+ */
460
+ static void arithmetic_command(command *cmd,
461
+ uint8_t cc,
462
+ const void* key,
463
+ size_t keylen,
464
+ uint64_t delta,
465
+ uint64_t initial,
466
+ uint32_t exptime)
467
+ {
468
+ memset(cmd, 0, sizeof (cmd->incr));
469
+ cmd->incr.message.header.request.magic= PROTOCOL_BINARY_REQ;
470
+ cmd->incr.message.header.request.opcode= cc;
471
+ cmd->incr.message.header.request.keylen= (uint16_t)keylen;
472
+ cmd->incr.message.header.request.extlen= 20;
473
+ cmd->incr.message.header.request.bodylen= (uint32_t)(keylen + 20);
474
+ cmd->incr.message.header.request.opaque= 0xdeadbeef;
475
+ cmd->incr.message.body.delta= memcached_htonll(delta);
476
+ cmd->incr.message.body.initial= memcached_htonll(initial);
477
+ cmd->incr.message.body.expiration= htonl(exptime);
478
+
479
+ off_t key_offset= sizeof (protocol_binary_request_no_extras) + 20;
480
+ memcpy(cmd->bytes + key_offset, key, keylen);
481
+ }
482
+
483
+ /**
484
+ * Validate the response header from the server
485
+ * @param rsp the response to check
486
+ * @param cc the expected command
487
+ * @param status the expected status
488
+ */
489
+ static enum test_return do_validate_response_header(response *rsp,
490
+ uint8_t cc, uint16_t status)
491
+ {
492
+ verify(rsp->plain.message.header.response.magic == PROTOCOL_BINARY_RES);
493
+ verify(rsp->plain.message.header.response.opcode == cc);
494
+ verify(rsp->plain.message.header.response.datatype == PROTOCOL_BINARY_RAW_BYTES);
495
+ verify(rsp->plain.message.header.response.status == status);
496
+ verify(rsp->plain.message.header.response.opaque == 0xdeadbeef);
497
+
498
+ if (status == PROTOCOL_BINARY_RESPONSE_SUCCESS)
499
+ {
500
+ switch (cc) {
501
+ case PROTOCOL_BINARY_CMD_ADDQ:
502
+ case PROTOCOL_BINARY_CMD_APPENDQ:
503
+ case PROTOCOL_BINARY_CMD_DECREMENTQ:
504
+ case PROTOCOL_BINARY_CMD_DELETEQ:
505
+ case PROTOCOL_BINARY_CMD_FLUSHQ:
506
+ case PROTOCOL_BINARY_CMD_INCREMENTQ:
507
+ case PROTOCOL_BINARY_CMD_PREPENDQ:
508
+ case PROTOCOL_BINARY_CMD_QUITQ:
509
+ case PROTOCOL_BINARY_CMD_REPLACEQ:
510
+ case PROTOCOL_BINARY_CMD_SETQ:
511
+ verify("Quiet command shouldn't return on success" == NULL);
512
+ default:
513
+ break;
514
+ }
515
+
516
+ switch (cc) {
517
+ case PROTOCOL_BINARY_CMD_ADD:
518
+ case PROTOCOL_BINARY_CMD_REPLACE:
519
+ case PROTOCOL_BINARY_CMD_SET:
520
+ case PROTOCOL_BINARY_CMD_APPEND:
521
+ case PROTOCOL_BINARY_CMD_PREPEND:
522
+ verify(rsp->plain.message.header.response.keylen == 0);
523
+ verify(rsp->plain.message.header.response.extlen == 0);
524
+ verify(rsp->plain.message.header.response.bodylen == 0);
525
+ verify(rsp->plain.message.header.response.cas != 0);
526
+ break;
527
+ case PROTOCOL_BINARY_CMD_FLUSH:
528
+ case PROTOCOL_BINARY_CMD_NOOP:
529
+ case PROTOCOL_BINARY_CMD_QUIT:
530
+ case PROTOCOL_BINARY_CMD_DELETE:
531
+ verify(rsp->plain.message.header.response.keylen == 0);
532
+ verify(rsp->plain.message.header.response.extlen == 0);
533
+ verify(rsp->plain.message.header.response.bodylen == 0);
534
+ verify(rsp->plain.message.header.response.cas == 0);
535
+ break;
536
+
537
+ case PROTOCOL_BINARY_CMD_DECREMENT:
538
+ case PROTOCOL_BINARY_CMD_INCREMENT:
539
+ verify(rsp->plain.message.header.response.keylen == 0);
540
+ verify(rsp->plain.message.header.response.extlen == 0);
541
+ verify(rsp->plain.message.header.response.bodylen == 8);
542
+ verify(rsp->plain.message.header.response.cas != 0);
543
+ break;
544
+
545
+ case PROTOCOL_BINARY_CMD_STAT:
546
+ verify(rsp->plain.message.header.response.extlen == 0);
547
+ /* key and value exists in all packets except in the terminating */
548
+ verify(rsp->plain.message.header.response.cas == 0);
549
+ break;
550
+
551
+ case PROTOCOL_BINARY_CMD_VERSION:
552
+ verify(rsp->plain.message.header.response.keylen == 0);
553
+ verify(rsp->plain.message.header.response.extlen == 0);
554
+ verify(rsp->plain.message.header.response.bodylen != 0);
555
+ verify(rsp->plain.message.header.response.cas == 0);
556
+ break;
557
+
558
+ case PROTOCOL_BINARY_CMD_GET:
559
+ case PROTOCOL_BINARY_CMD_GETQ:
560
+ verify(rsp->plain.message.header.response.keylen == 0);
561
+ verify(rsp->plain.message.header.response.extlen == 4);
562
+ verify(rsp->plain.message.header.response.cas != 0);
563
+ break;
564
+
565
+ case PROTOCOL_BINARY_CMD_GETK:
566
+ case PROTOCOL_BINARY_CMD_GETKQ:
567
+ verify(rsp->plain.message.header.response.keylen != 0);
568
+ verify(rsp->plain.message.header.response.extlen == 4);
569
+ verify(rsp->plain.message.header.response.cas != 0);
570
+ break;
571
+
572
+ default:
573
+ /* Undefined command code */
574
+ break;
575
+ }
576
+ }
577
+ else
578
+ {
579
+ verify(rsp->plain.message.header.response.cas == 0);
580
+ verify(rsp->plain.message.header.response.extlen == 0);
581
+ if (cc != PROTOCOL_BINARY_CMD_GETK)
582
+ {
583
+ verify(rsp->plain.message.header.response.keylen == 0);
584
+ }
585
+ }
586
+
587
+ return TEST_PASS;
588
+ }
589
+
590
+ /* We call verify(validate_response_header), but that macro
591
+ * expects a boolean expression, and the function returns
592
+ * an enum.... Let's just create a macro to avoid cluttering
593
+ * the code with all of the == TEST_PASS ;-)
594
+ */
595
+ #define validate_response_header(a,b,c) \
596
+ do_validate_response_header(a,b,c) == TEST_PASS
597
+
598
+
599
+ static enum test_return send_binary_noop(void)
600
+ {
601
+ command cmd;
602
+ raw_command(&cmd, PROTOCOL_BINARY_CMD_NOOP, NULL, 0, NULL, 0);
603
+ execute(send_packet(&cmd));
604
+ return TEST_PASS;
605
+ }
606
+
607
+ static enum test_return receive_binary_noop(void)
608
+ {
609
+ response rsp;
610
+ execute(recv_packet(&rsp));
611
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_NOOP,
612
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
613
+ return TEST_PASS;
614
+ }
615
+
616
+ static enum test_return test_binary_noop(void)
617
+ {
618
+ execute(send_binary_noop());
619
+ execute(receive_binary_noop());
620
+ return TEST_PASS;
621
+ }
622
+
623
+ static enum test_return test_binary_quit_impl(uint8_t cc)
624
+ {
625
+ command cmd;
626
+ response rsp;
627
+ raw_command(&cmd, cc, NULL, 0, NULL, 0);
628
+
629
+ execute(send_packet(&cmd));
630
+ if (cc == PROTOCOL_BINARY_CMD_QUIT)
631
+ {
632
+ execute(recv_packet(&rsp));
633
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_QUIT,
634
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
635
+ }
636
+
637
+ /* Socket should be closed now, read should return EXIT_SUCCESS */
638
+ verify(timeout_io_op(sock, POLLIN, rsp.bytes, sizeof(rsp.bytes)) == 0);
639
+
640
+ return TEST_PASS_RECONNECT;
641
+ }
642
+
643
+ static enum test_return test_binary_quit(void)
644
+ {
645
+ return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUIT);
646
+ }
647
+
648
+ static enum test_return test_binary_quitq(void)
649
+ {
650
+ return test_binary_quit_impl(PROTOCOL_BINARY_CMD_QUITQ);
651
+ }
652
+
653
+ static enum test_return test_binary_set_impl(const char* key, uint8_t cc)
654
+ {
655
+ command cmd;
656
+ response rsp;
657
+
658
+ uint64_t value= 0xdeadbeefdeadcafeULL;
659
+ storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
660
+
661
+ /* set should always work */
662
+ for (int ii= 0; ii < 10; ii++)
663
+ {
664
+ if (ii == 0)
665
+ execute(send_packet(&cmd));
666
+ else
667
+ execute(resend_packet(&cmd));
668
+
669
+ if (cc == PROTOCOL_BINARY_CMD_SET)
670
+ {
671
+ execute(recv_packet(&rsp));
672
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
673
+ }
674
+ else
675
+ execute(test_binary_noop());
676
+ }
677
+
678
+ /*
679
+ * We need to get the current CAS id, and at this time we haven't
680
+ * verified that we have a working get
681
+ */
682
+ if (cc == PROTOCOL_BINARY_CMD_SETQ)
683
+ {
684
+ cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SET;
685
+ execute(resend_packet(&cmd));
686
+ execute(recv_packet(&rsp));
687
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
688
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
689
+ cmd.set.message.header.request.opcode= PROTOCOL_BINARY_CMD_SETQ;
690
+ }
691
+
692
+ /* try to set with the correct CAS value */
693
+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
694
+ execute(resend_packet(&cmd));
695
+ if (cc == PROTOCOL_BINARY_CMD_SET)
696
+ {
697
+ execute(recv_packet(&rsp));
698
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
699
+ }
700
+ else
701
+ execute(test_binary_noop());
702
+
703
+ /* try to set with an incorrect CAS value */
704
+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
705
+ execute(resend_packet(&cmd));
706
+ execute(send_binary_noop());
707
+ execute(recv_packet(&rsp));
708
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
709
+ execute(receive_binary_noop());
710
+
711
+ return TEST_PASS;
712
+ }
713
+
714
+ static enum test_return test_binary_set(void)
715
+ {
716
+ return test_binary_set_impl("test_binary_set", PROTOCOL_BINARY_CMD_SET);
717
+ }
718
+
719
+ static enum test_return test_binary_setq(void)
720
+ {
721
+ return test_binary_set_impl("test_binary_setq", PROTOCOL_BINARY_CMD_SETQ);
722
+ }
723
+
724
+ static enum test_return test_binary_add_impl(const char* key, uint8_t cc)
725
+ {
726
+ command cmd;
727
+ response rsp;
728
+ uint64_t value= 0xdeadbeefdeadcafeULL;
729
+ storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
730
+
731
+ /* first add should work, rest of them should fail (even with cas
732
+ as wildcard */
733
+ for (int ii=0; ii < 10; ii++)
734
+ {
735
+ if (ii == 0)
736
+ execute(send_packet(&cmd));
737
+ else
738
+ execute(resend_packet(&cmd));
739
+
740
+ if (cc == PROTOCOL_BINARY_CMD_ADD || ii > 0)
741
+ {
742
+ uint16_t expected_result;
743
+ if (ii == 0)
744
+ expected_result= PROTOCOL_BINARY_RESPONSE_SUCCESS;
745
+ else
746
+ expected_result= PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS;
747
+
748
+ execute(send_binary_noop());
749
+ execute(recv_packet(&rsp));
750
+ execute(receive_binary_noop());
751
+ verify(validate_response_header(&rsp, cc, expected_result));
752
+ }
753
+ else
754
+ execute(test_binary_noop());
755
+ }
756
+
757
+ return TEST_PASS;
758
+ }
759
+
760
+ static enum test_return test_binary_add(void)
761
+ {
762
+ return test_binary_add_impl("test_binary_add", PROTOCOL_BINARY_CMD_ADD);
763
+ }
764
+
765
+ static enum test_return test_binary_addq(void)
766
+ {
767
+ return test_binary_add_impl("test_binary_addq", PROTOCOL_BINARY_CMD_ADDQ);
768
+ }
769
+
770
+ static enum test_return binary_set_item(const char *key, const char *value)
771
+ {
772
+ command cmd;
773
+ response rsp;
774
+ storage_command(&cmd, PROTOCOL_BINARY_CMD_SET, key, strlen(key),
775
+ value, strlen(value), 0, 0);
776
+ execute(send_packet(&cmd));
777
+ execute(recv_packet(&rsp));
778
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_SET,
779
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
780
+ return TEST_PASS;
781
+ }
782
+
783
+ static enum test_return test_binary_replace_impl(const char* key, uint8_t cc)
784
+ {
785
+ command cmd;
786
+ response rsp;
787
+ uint64_t value= 0xdeadbeefdeadcafeULL;
788
+ storage_command(&cmd, cc, key, strlen(key), &value, sizeof (value), 0, 0);
789
+
790
+ /* first replace should fail, successive should succeed (when the
791
+ item is added! */
792
+ for (int ii= 0; ii < 10; ii++)
793
+ {
794
+ if (ii == 0)
795
+ execute(send_packet(&cmd));
796
+ else
797
+ execute(resend_packet(&cmd));
798
+
799
+ if (cc == PROTOCOL_BINARY_CMD_REPLACE || ii == 0)
800
+ {
801
+ uint16_t expected_result;
802
+ if (ii == 0)
803
+ expected_result=PROTOCOL_BINARY_RESPONSE_KEY_ENOENT;
804
+ else
805
+ expected_result=PROTOCOL_BINARY_RESPONSE_SUCCESS;
806
+
807
+ execute(send_binary_noop());
808
+ execute(recv_packet(&rsp));
809
+ execute(receive_binary_noop());
810
+ verify(validate_response_header(&rsp, cc, expected_result));
811
+
812
+ if (ii == 0)
813
+ execute(binary_set_item(key, key));
814
+ }
815
+ else
816
+ execute(test_binary_noop());
817
+ }
818
+
819
+ /* verify that replace with CAS value works! */
820
+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas);
821
+ execute(resend_packet(&cmd));
822
+
823
+ if (cc == PROTOCOL_BINARY_CMD_REPLACE)
824
+ {
825
+ execute(recv_packet(&rsp));
826
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
827
+ }
828
+ else
829
+ execute(test_binary_noop());
830
+
831
+ /* try to set with an incorrect CAS value */
832
+ cmd.plain.message.header.request.cas= memcached_htonll(rsp.plain.message.header.response.cas - 1);
833
+ execute(resend_packet(&cmd));
834
+ execute(send_binary_noop());
835
+ execute(recv_packet(&rsp));
836
+ execute(receive_binary_noop());
837
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_EEXISTS));
838
+
839
+ return TEST_PASS;
840
+ }
841
+
842
+ static enum test_return test_binary_replace(void)
843
+ {
844
+ return test_binary_replace_impl("test_binary_replace", PROTOCOL_BINARY_CMD_REPLACE);
845
+ }
846
+
847
+ static enum test_return test_binary_replaceq(void)
848
+ {
849
+ return test_binary_replace_impl("test_binary_replaceq", PROTOCOL_BINARY_CMD_REPLACEQ);
850
+ }
851
+
852
+ static enum test_return test_binary_delete_impl(const char *key, uint8_t cc)
853
+ {
854
+ command cmd;
855
+ response rsp;
856
+ raw_command(&cmd, cc, key, strlen(key), NULL, 0);
857
+
858
+ /* The delete shouldn't work the first time, because the item isn't there */
859
+ execute(send_packet(&cmd));
860
+ execute(send_binary_noop());
861
+ execute(recv_packet(&rsp));
862
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
863
+ execute(receive_binary_noop());
864
+ execute(binary_set_item(key, key));
865
+
866
+ /* The item should be present now, resend*/
867
+ execute(resend_packet(&cmd));
868
+ if (cc == PROTOCOL_BINARY_CMD_DELETE)
869
+ {
870
+ execute(recv_packet(&rsp));
871
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
872
+ }
873
+
874
+ execute(test_binary_noop());
875
+
876
+ return TEST_PASS;
877
+ }
878
+
879
+ static enum test_return test_binary_delete(void)
880
+ {
881
+ return test_binary_delete_impl("test_binary_delete", PROTOCOL_BINARY_CMD_DELETE);
882
+ }
883
+
884
+ static enum test_return test_binary_deleteq(void)
885
+ {
886
+ return test_binary_delete_impl("test_binary_deleteq", PROTOCOL_BINARY_CMD_DELETEQ);
887
+ }
888
+
889
+ static enum test_return test_binary_get_impl(const char *key, uint8_t cc)
890
+ {
891
+ command cmd;
892
+ response rsp;
893
+
894
+ raw_command(&cmd, cc, key, strlen(key), NULL, 0);
895
+ execute(send_packet(&cmd));
896
+ execute(send_binary_noop());
897
+
898
+ if (cc == PROTOCOL_BINARY_CMD_GET || cc == PROTOCOL_BINARY_CMD_GETK)
899
+ {
900
+ execute(recv_packet(&rsp));
901
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
902
+ }
903
+
904
+ execute(receive_binary_noop());
905
+
906
+ execute(binary_set_item(key, key));
907
+ execute(resend_packet(&cmd));
908
+ execute(send_binary_noop());
909
+
910
+ execute(recv_packet(&rsp));
911
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
912
+ execute(receive_binary_noop());
913
+
914
+ return TEST_PASS;
915
+ }
916
+
917
+ static enum test_return test_binary_get(void)
918
+ {
919
+ return test_binary_get_impl("test_binary_get", PROTOCOL_BINARY_CMD_GET);
920
+ }
921
+
922
+ static enum test_return test_binary_getk(void)
923
+ {
924
+ return test_binary_get_impl("test_binary_getk", PROTOCOL_BINARY_CMD_GETK);
925
+ }
926
+
927
+ static enum test_return test_binary_getq(void)
928
+ {
929
+ return test_binary_get_impl("test_binary_getq", PROTOCOL_BINARY_CMD_GETQ);
930
+ }
931
+
932
+ static enum test_return test_binary_getkq(void)
933
+ {
934
+ return test_binary_get_impl("test_binary_getkq", PROTOCOL_BINARY_CMD_GETKQ);
935
+ }
936
+
937
+ static enum test_return test_binary_incr_impl(const char* key, uint8_t cc)
938
+ {
939
+ command cmd;
940
+ response rsp;
941
+ arithmetic_command(&cmd, cc, key, strlen(key), 1, 0, 0);
942
+
943
+ uint64_t ii;
944
+ for (ii= 0; ii < 10; ++ii)
945
+ {
946
+ if (ii == 0)
947
+ execute(send_packet(&cmd));
948
+ else
949
+ execute(resend_packet(&cmd));
950
+
951
+ if (cc == PROTOCOL_BINARY_CMD_INCREMENT)
952
+ {
953
+ execute(recv_packet(&rsp));
954
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
955
+ verify(memcached_ntohll(rsp.incr.message.body.value) == ii);
956
+ }
957
+ else
958
+ execute(test_binary_noop());
959
+ }
960
+
961
+ /* @todo add incorrect CAS */
962
+ return TEST_PASS;
963
+ }
964
+
965
+ static enum test_return test_binary_incr(void)
966
+ {
967
+ return test_binary_incr_impl("test_binary_incr", PROTOCOL_BINARY_CMD_INCREMENT);
968
+ }
969
+
970
+ static enum test_return test_binary_incrq(void)
971
+ {
972
+ return test_binary_incr_impl("test_binary_incrq", PROTOCOL_BINARY_CMD_INCREMENTQ);
973
+ }
974
+
975
+ static enum test_return test_binary_decr_impl(const char* key, uint8_t cc)
976
+ {
977
+ command cmd;
978
+ response rsp;
979
+ arithmetic_command(&cmd, cc, key, strlen(key), 1, 9, 0);
980
+
981
+ int ii;
982
+ for (ii= 9; ii > -1; --ii)
983
+ {
984
+ if (ii == 9)
985
+ execute(send_packet(&cmd));
986
+ else
987
+ execute(resend_packet(&cmd));
988
+
989
+ if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
990
+ {
991
+ execute(recv_packet(&rsp));
992
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
993
+ verify(memcached_ntohll(rsp.decr.message.body.value) == (uint64_t)ii);
994
+ }
995
+ else
996
+ execute(test_binary_noop());
997
+ }
998
+
999
+ /* decr 0 should not wrap */
1000
+ execute(resend_packet(&cmd));
1001
+ if (cc == PROTOCOL_BINARY_CMD_DECREMENT)
1002
+ {
1003
+ execute(recv_packet(&rsp));
1004
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
1005
+ verify(memcached_ntohll(rsp.decr.message.body.value) == 0);
1006
+ }
1007
+ else
1008
+ {
1009
+ /* @todo get the value and verify! */
1010
+
1011
+ }
1012
+
1013
+ /* @todo add incorrect cas */
1014
+ execute(test_binary_noop());
1015
+ return TEST_PASS;
1016
+ }
1017
+
1018
+ static enum test_return test_binary_decr(void)
1019
+ {
1020
+ return test_binary_decr_impl("test_binary_decr",
1021
+ PROTOCOL_BINARY_CMD_DECREMENT);
1022
+ }
1023
+
1024
+ static enum test_return test_binary_decrq(void)
1025
+ {
1026
+ return test_binary_decr_impl("test_binary_decrq",
1027
+ PROTOCOL_BINARY_CMD_DECREMENTQ);
1028
+ }
1029
+
1030
+ static enum test_return test_binary_version(void)
1031
+ {
1032
+ command cmd;
1033
+ response rsp;
1034
+ raw_command(&cmd, PROTOCOL_BINARY_CMD_VERSION, NULL, 0, NULL, 0);
1035
+
1036
+ execute(send_packet(&cmd));
1037
+ execute(recv_packet(&rsp));
1038
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_VERSION,
1039
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
1040
+
1041
+ return TEST_PASS;
1042
+ }
1043
+
1044
+ static enum test_return test_binary_flush_impl(const char *key, uint8_t cc)
1045
+ {
1046
+ command cmd;
1047
+ response rsp;
1048
+
1049
+ for (int ii= 0; ii < 2; ++ii)
1050
+ {
1051
+ execute(binary_set_item(key, key));
1052
+ flush_command(&cmd, cc, 0, ii == 0);
1053
+ execute(send_packet(&cmd));
1054
+
1055
+ if (cc == PROTOCOL_BINARY_CMD_FLUSH)
1056
+ {
1057
+ execute(recv_packet(&rsp));
1058
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
1059
+ }
1060
+ else
1061
+ execute(test_binary_noop());
1062
+
1063
+ raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
1064
+ execute(send_packet(&cmd));
1065
+ execute(recv_packet(&rsp));
1066
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
1067
+ PROTOCOL_BINARY_RESPONSE_KEY_ENOENT));
1068
+ }
1069
+
1070
+ return TEST_PASS;
1071
+ }
1072
+
1073
+ static enum test_return test_binary_flush(void)
1074
+ {
1075
+ return test_binary_flush_impl("test_binary_flush", PROTOCOL_BINARY_CMD_FLUSH);
1076
+ }
1077
+
1078
+ static enum test_return test_binary_flushq(void)
1079
+ {
1080
+ return test_binary_flush_impl("test_binary_flushq", PROTOCOL_BINARY_CMD_FLUSHQ);
1081
+ }
1082
+
1083
+ static enum test_return test_binary_concat_impl(const char *key, uint8_t cc)
1084
+ {
1085
+ command cmd;
1086
+ response rsp;
1087
+ const char *value;
1088
+
1089
+ if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
1090
+ value="hello";
1091
+ else
1092
+ value=" world";
1093
+
1094
+ execute(binary_set_item(key, value));
1095
+
1096
+ if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_APPENDQ)
1097
+ value=" world";
1098
+ else
1099
+ value="hello";
1100
+
1101
+ raw_command(&cmd, cc, key, strlen(key), value, strlen(value));
1102
+ execute(send_packet(&cmd));
1103
+ if (cc == PROTOCOL_BINARY_CMD_APPEND || cc == PROTOCOL_BINARY_CMD_PREPEND)
1104
+ {
1105
+ execute(recv_packet(&rsp));
1106
+ verify(validate_response_header(&rsp, cc, PROTOCOL_BINARY_RESPONSE_SUCCESS));
1107
+ }
1108
+ else
1109
+ execute(test_binary_noop());
1110
+
1111
+ raw_command(&cmd, PROTOCOL_BINARY_CMD_GET, key, strlen(key), NULL, 0);
1112
+ execute(send_packet(&cmd));
1113
+ execute(recv_packet(&rsp));
1114
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_GET,
1115
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
1116
+ verify(rsp.plain.message.header.response.bodylen - 4 == 11);
1117
+ verify(memcmp(rsp.bytes + 28, "hello world", 11) == 0);
1118
+
1119
+ return TEST_PASS;
1120
+ }
1121
+
1122
+ static enum test_return test_binary_append(void)
1123
+ {
1124
+ return test_binary_concat_impl("test_binary_append", PROTOCOL_BINARY_CMD_APPEND);
1125
+ }
1126
+
1127
+ static enum test_return test_binary_prepend(void)
1128
+ {
1129
+ return test_binary_concat_impl("test_binary_prepend", PROTOCOL_BINARY_CMD_PREPEND);
1130
+ }
1131
+
1132
+ static enum test_return test_binary_appendq(void)
1133
+ {
1134
+ return test_binary_concat_impl("test_binary_appendq", PROTOCOL_BINARY_CMD_APPENDQ);
1135
+ }
1136
+
1137
+ static enum test_return test_binary_prependq(void)
1138
+ {
1139
+ return test_binary_concat_impl("test_binary_prependq", PROTOCOL_BINARY_CMD_PREPENDQ);
1140
+ }
1141
+
1142
+ static enum test_return test_binary_stat(void)
1143
+ {
1144
+ command cmd;
1145
+ response rsp;
1146
+
1147
+ raw_command(&cmd, PROTOCOL_BINARY_CMD_STAT, NULL, 0, NULL, 0);
1148
+ execute(send_packet(&cmd));
1149
+
1150
+ do
1151
+ {
1152
+ execute(recv_packet(&rsp));
1153
+ verify(validate_response_header(&rsp, PROTOCOL_BINARY_CMD_STAT,
1154
+ PROTOCOL_BINARY_RESPONSE_SUCCESS));
1155
+ } while (rsp.plain.message.header.response.keylen != 0);
1156
+
1157
+ return TEST_PASS;
1158
+ }
1159
+
1160
+ static enum test_return send_string(const char *cmd)
1161
+ {
1162
+ execute(retry_write(cmd, strlen(cmd)));
1163
+ return TEST_PASS;
1164
+ }
1165
+
1166
+ static enum test_return receive_line(char *buffer, size_t size)
1167
+ {
1168
+ size_t offset= 0;
1169
+ while (offset < size)
1170
+ {
1171
+ execute(retry_read(buffer + offset, 1));
1172
+ if (buffer[offset] == '\n')
1173
+ {
1174
+ if (offset + 1 < size)
1175
+ {
1176
+ buffer[offset + 1]= '\0';
1177
+ return TEST_PASS;
1178
+ }
1179
+ else
1180
+ return TEST_FAIL;
1181
+ }
1182
+ ++offset;
1183
+ }
1184
+
1185
+ return TEST_FAIL;
1186
+ }
1187
+
1188
+ static enum test_return receive_response(const char *msg) {
1189
+ char buffer[80];
1190
+ execute(receive_line(buffer, sizeof(buffer)));
1191
+ if (strcmp(msg, buffer) != 0) {
1192
+ fprintf(stderr, "[%s]\n", buffer);
1193
+ }
1194
+ verify(strcmp(msg, buffer) == 0);
1195
+ return TEST_PASS;
1196
+ }
1197
+
1198
+ static enum test_return receive_error_response(void)
1199
+ {
1200
+ char buffer[80];
1201
+ execute(receive_line(buffer, sizeof(buffer)));
1202
+ verify(strncmp(buffer, "ERROR", 5) == 0 ||
1203
+ strncmp(buffer, "CLIENT_ERROR", 12) == 0 ||
1204
+ strncmp(buffer, "SERVER_ERROR", 12) == 0);
1205
+ return TEST_PASS;
1206
+ }
1207
+
1208
+ static enum test_return test_ascii_quit(void)
1209
+ {
1210
+ /* Verify that quit handles unknown options */
1211
+ execute(send_string("quit foo bar\r\n"));
1212
+ execute(receive_error_response());
1213
+
1214
+ /* quit doesn't support noreply */
1215
+ execute(send_string("quit noreply\r\n"));
1216
+ execute(receive_error_response());
1217
+
1218
+ /* Verify that quit works */
1219
+ execute(send_string("quit\r\n"));
1220
+
1221
+ /* Socket should be closed now, read should return EXIT_SUCCESS */
1222
+ char buffer[80];
1223
+ verify(timeout_io_op(sock, POLLIN, buffer, sizeof(buffer)) == 0);
1224
+ return TEST_PASS_RECONNECT;
1225
+
1226
+ }
1227
+
1228
+ static enum test_return test_ascii_version(void)
1229
+ {
1230
+ /* Verify that version command handles unknown options */
1231
+ execute(send_string("version foo bar\r\n"));
1232
+ execute(receive_error_response());
1233
+
1234
+ /* version doesn't support noreply */
1235
+ execute(send_string("version noreply\r\n"));
1236
+ execute(receive_error_response());
1237
+
1238
+ /* Verify that verify works */
1239
+ execute(send_string("version\r\n"));
1240
+ char buffer[256];
1241
+ execute(receive_line(buffer, sizeof(buffer)));
1242
+ verify(strncmp(buffer, "VERSION ", 8) == 0);
1243
+
1244
+ return TEST_PASS;
1245
+ }
1246
+
1247
+ static enum test_return test_ascii_verbosity(void)
1248
+ {
1249
+ /* This command does not adhere to the spec! */
1250
+ execute(send_string("verbosity foo bar my\r\n"));
1251
+ execute(receive_error_response());
1252
+
1253
+ execute(send_string("verbosity noreply\r\n"));
1254
+ execute(receive_error_response());
1255
+
1256
+ execute(send_string("verbosity 0 noreply\r\n"));
1257
+ execute(test_ascii_version());
1258
+
1259
+ execute(send_string("verbosity\r\n"));
1260
+ execute(receive_error_response());
1261
+
1262
+ execute(send_string("verbosity 1\r\n"));
1263
+ execute(receive_response("OK\r\n"));
1264
+
1265
+ execute(send_string("verbosity 0\r\n"));
1266
+ execute(receive_response("OK\r\n"));
1267
+
1268
+ return TEST_PASS;
1269
+ }
1270
+
1271
+
1272
+
1273
+ static enum test_return test_ascii_set_impl(const char* key, bool noreply)
1274
+ {
1275
+ /* @todo add tests for bogus format! */
1276
+ char buffer[1024];
1277
+ snprintf(buffer, sizeof(buffer), "set %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
1278
+ execute(send_string(buffer));
1279
+
1280
+ if (!noreply)
1281
+ execute(receive_response("STORED\r\n"));
1282
+
1283
+ return test_ascii_version();
1284
+ }
1285
+
1286
+ static enum test_return test_ascii_set(void)
1287
+ {
1288
+ return test_ascii_set_impl("test_ascii_set", false);
1289
+ }
1290
+
1291
+ static enum test_return test_ascii_set_noreply(void)
1292
+ {
1293
+ return test_ascii_set_impl("test_ascii_set_noreply", true);
1294
+ }
1295
+
1296
+ static enum test_return test_ascii_add_impl(const char* key, bool noreply)
1297
+ {
1298
+ /* @todo add tests for bogus format! */
1299
+ char buffer[1024];
1300
+ snprintf(buffer, sizeof(buffer), "add %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
1301
+ execute(send_string(buffer));
1302
+
1303
+ if (!noreply)
1304
+ execute(receive_response("STORED\r\n"));
1305
+
1306
+ execute(send_string(buffer));
1307
+
1308
+ if (!noreply)
1309
+ execute(receive_response("NOT_STORED\r\n"));
1310
+
1311
+ return test_ascii_version();
1312
+ }
1313
+
1314
+ static enum test_return test_ascii_add(void)
1315
+ {
1316
+ return test_ascii_add_impl("test_ascii_add", false);
1317
+ }
1318
+
1319
+ static enum test_return test_ascii_add_noreply(void)
1320
+ {
1321
+ return test_ascii_add_impl("test_ascii_add_noreply", true);
1322
+ }
1323
+
1324
+ static enum test_return ascii_get_unknown_value(char **key, char **value, ssize_t *ndata)
1325
+ {
1326
+ char buffer[1024];
1327
+
1328
+ execute(receive_line(buffer, sizeof(buffer)));
1329
+ verify(strncmp(buffer, "VALUE ", 6) == 0);
1330
+ char *end= strchr(buffer + 6, ' ');
1331
+ verify(end != NULL);
1332
+ *end= '\0';
1333
+ *key= strdup(buffer + 6);
1334
+ verify(*key != NULL);
1335
+ char *ptr= end + 1;
1336
+
1337
+ unsigned long val= strtoul(ptr, &end, 10); /* flags */
1338
+ verify(ptr != end);
1339
+ verify(val == 0);
1340
+ verify(end != NULL);
1341
+ *ndata = (ssize_t)strtoul(end, &end, 10); /* size */
1342
+ verify(ptr != end);
1343
+ verify(end != NULL);
1344
+ while (*end != '\n' && isspace(*end))
1345
+ ++end;
1346
+ verify(*end == '\n');
1347
+
1348
+ *value= static_cast<char*>(malloc((size_t)*ndata));
1349
+ verify(*value != NULL);
1350
+
1351
+ execute(retry_read(*value, (size_t)*ndata));
1352
+
1353
+ execute(retry_read(buffer, 2));
1354
+ verify(memcmp(buffer, "\r\n", 2) == 0);
1355
+
1356
+ return TEST_PASS;
1357
+ }
1358
+
1359
+ static enum test_return ascii_get_value(const char *key, const char *value)
1360
+ {
1361
+
1362
+ char buffer[1024];
1363
+ size_t datasize= strlen(value);
1364
+
1365
+ verify(datasize < sizeof(buffer));
1366
+ execute(receive_line(buffer, sizeof(buffer)));
1367
+ verify(strncmp(buffer, "VALUE ", 6) == 0);
1368
+ verify(strncmp(buffer + 6, key, strlen(key)) == 0);
1369
+ char *ptr= buffer + 6 + strlen(key) + 1;
1370
+ char *end;
1371
+
1372
+ unsigned long val= strtoul(ptr, &end, 10); /* flags */
1373
+ verify(ptr != end);
1374
+ verify(val == 0);
1375
+ verify(end != NULL);
1376
+ val= strtoul(end, &end, 10); /* size */
1377
+ verify(ptr != end);
1378
+ verify(val == datasize);
1379
+ verify(end != NULL);
1380
+ while (*end != '\n' && isspace(*end))
1381
+ ++end;
1382
+ verify(*end == '\n');
1383
+
1384
+ execute(retry_read(buffer, datasize));
1385
+ verify(memcmp(buffer, value, datasize) == 0);
1386
+
1387
+ execute(retry_read(buffer, 2));
1388
+ verify(memcmp(buffer, "\r\n", 2) == 0);
1389
+
1390
+ return TEST_PASS;
1391
+ }
1392
+
1393
+ static enum test_return ascii_get_item(const char *key, const char *value,
1394
+ bool exist)
1395
+ {
1396
+ char buffer[1024];
1397
+ size_t datasize= 0;
1398
+ if (value != NULL)
1399
+ datasize= strlen(value);
1400
+
1401
+ verify(datasize < sizeof(buffer));
1402
+ snprintf(buffer, sizeof(buffer), "get %s\r\n", key);
1403
+ execute(send_string(buffer));
1404
+
1405
+ if (exist)
1406
+ execute(ascii_get_value(key, value));
1407
+
1408
+ execute(retry_read(buffer, 5));
1409
+ verify(memcmp(buffer, "END\r\n", 5) == 0);
1410
+
1411
+ return TEST_PASS;
1412
+ }
1413
+
1414
+ static enum test_return ascii_gets_value(const char *key, const char *value,
1415
+ unsigned long *cas)
1416
+ {
1417
+
1418
+ char buffer[1024];
1419
+ size_t datasize= strlen(value);
1420
+
1421
+ verify(datasize < sizeof(buffer));
1422
+ execute(receive_line(buffer, sizeof(buffer)));
1423
+ verify(strncmp(buffer, "VALUE ", 6) == 0);
1424
+ verify(strncmp(buffer + 6, key, strlen(key)) == 0);
1425
+ char *ptr= buffer + 6 + strlen(key) + 1;
1426
+ char *end;
1427
+
1428
+ unsigned long val= strtoul(ptr, &end, 10); /* flags */
1429
+ verify(ptr != end);
1430
+ verify(val == 0);
1431
+ verify(end != NULL);
1432
+ val= strtoul(end, &end, 10); /* size */
1433
+ verify(ptr != end);
1434
+ verify(val == datasize);
1435
+ verify(end != NULL);
1436
+ *cas= strtoul(end, &end, 10); /* cas */
1437
+ verify(ptr != end);
1438
+ verify(val == datasize);
1439
+ verify(end != NULL);
1440
+
1441
+ while (*end != '\n' && isspace(*end))
1442
+ ++end;
1443
+ verify(*end == '\n');
1444
+
1445
+ execute(retry_read(buffer, datasize));
1446
+ verify(memcmp(buffer, value, datasize) == 0);
1447
+
1448
+ execute(retry_read(buffer, 2));
1449
+ verify(memcmp(buffer, "\r\n", 2) == 0);
1450
+
1451
+ return TEST_PASS;
1452
+ }
1453
+
1454
+ static enum test_return ascii_gets_item(const char *key, const char *value,
1455
+ bool exist, unsigned long *cas)
1456
+ {
1457
+ char buffer[1024];
1458
+ size_t datasize= 0;
1459
+ if (value != NULL)
1460
+ datasize= strlen(value);
1461
+
1462
+ verify(datasize < sizeof(buffer));
1463
+ snprintf(buffer, sizeof(buffer), "gets %s\r\n", key);
1464
+ execute(send_string(buffer));
1465
+
1466
+ if (exist)
1467
+ execute(ascii_gets_value(key, value, cas));
1468
+
1469
+ execute(retry_read(buffer, 5));
1470
+ verify(memcmp(buffer, "END\r\n", 5) == 0);
1471
+
1472
+ return TEST_PASS;
1473
+ }
1474
+
1475
+ static enum test_return ascii_set_item(const char *key, const char *value)
1476
+ {
1477
+ char buffer[300];
1478
+ size_t len= strlen(value);
1479
+ snprintf(buffer, sizeof(buffer), "set %s 0 0 %u\r\n", key, (unsigned int)len);
1480
+ execute(send_string(buffer));
1481
+ execute(retry_write(value, len));
1482
+ execute(send_string("\r\n"));
1483
+ execute(receive_response("STORED\r\n"));
1484
+ return TEST_PASS;
1485
+ }
1486
+
1487
+ static enum test_return test_ascii_replace_impl(const char* key, bool noreply)
1488
+ {
1489
+ char buffer[1024];
1490
+ snprintf(buffer, sizeof(buffer), "replace %s 0 0 5%s\r\nvalue\r\n", key, noreply ? " noreply" : "");
1491
+ execute(send_string(buffer));
1492
+
1493
+ if (noreply)
1494
+ execute(test_ascii_version());
1495
+ else
1496
+ execute(receive_response("NOT_STORED\r\n"));
1497
+
1498
+ execute(ascii_set_item(key, "value"));
1499
+ execute(ascii_get_item(key, "value", true));
1500
+
1501
+
1502
+ execute(send_string(buffer));
1503
+
1504
+ if (noreply)
1505
+ execute(test_ascii_version());
1506
+ else
1507
+ execute(receive_response("STORED\r\n"));
1508
+
1509
+ return test_ascii_version();
1510
+ }
1511
+
1512
+ static enum test_return test_ascii_replace(void)
1513
+ {
1514
+ return test_ascii_replace_impl("test_ascii_replace", false);
1515
+ }
1516
+
1517
+ static enum test_return test_ascii_replace_noreply(void)
1518
+ {
1519
+ return test_ascii_replace_impl("test_ascii_replace_noreply", true);
1520
+ }
1521
+
1522
+ static enum test_return test_ascii_cas_impl(const char* key, bool noreply)
1523
+ {
1524
+ char buffer[1024];
1525
+ unsigned long cas;
1526
+
1527
+ execute(ascii_set_item(key, "value"));
1528
+ execute(ascii_gets_item(key, "value", true, &cas));
1529
+
1530
+ snprintf(buffer, sizeof(buffer), "cas %s 0 0 6 %lu%s\r\nvalue2\r\n", key, cas, noreply ? " noreply" : "");
1531
+ execute(send_string(buffer));
1532
+
1533
+ if (noreply)
1534
+ execute(test_ascii_version());
1535
+ else
1536
+ execute(receive_response("STORED\r\n"));
1537
+
1538
+ /* reexecute the same command should fail due to illegal cas */
1539
+ execute(send_string(buffer));
1540
+
1541
+ if (noreply)
1542
+ execute(test_ascii_version());
1543
+ else
1544
+ execute(receive_response("EXISTS\r\n"));
1545
+
1546
+ return test_ascii_version();
1547
+ }
1548
+
1549
+ static enum test_return test_ascii_cas(void)
1550
+ {
1551
+ return test_ascii_cas_impl("test_ascii_cas", false);
1552
+ }
1553
+
1554
+ static enum test_return test_ascii_cas_noreply(void)
1555
+ {
1556
+ return test_ascii_cas_impl("test_ascii_cas_noreply", true);
1557
+ }
1558
+
1559
+ static enum test_return test_ascii_delete_impl(const char *key, bool noreply)
1560
+ {
1561
+ execute(ascii_set_item(key, "value"));
1562
+
1563
+ execute(send_string("delete\r\n"));
1564
+ execute(receive_error_response());
1565
+ /* BUG: the server accepts delete a b */
1566
+ execute(send_string("delete a b c d e\r\n"));
1567
+ execute(receive_error_response());
1568
+
1569
+ char buffer[1024];
1570
+ snprintf(buffer, sizeof(buffer), "delete %s%s\r\n", key, noreply ? " noreply" : "");
1571
+ execute(send_string(buffer));
1572
+
1573
+ if (noreply)
1574
+ execute(test_ascii_version());
1575
+ else
1576
+ execute(receive_response("DELETED\r\n"));
1577
+
1578
+ execute(ascii_get_item(key, "value", false));
1579
+ execute(send_string(buffer));
1580
+ if (noreply)
1581
+ execute(test_ascii_version());
1582
+ else
1583
+ execute(receive_response("NOT_FOUND\r\n"));
1584
+
1585
+ return TEST_PASS;
1586
+ }
1587
+
1588
+ static enum test_return test_ascii_delete(void)
1589
+ {
1590
+ return test_ascii_delete_impl("test_ascii_delete", false);
1591
+ }
1592
+
1593
+ static enum test_return test_ascii_delete_noreply(void)
1594
+ {
1595
+ return test_ascii_delete_impl("test_ascii_delete_noreply", true);
1596
+ }
1597
+
1598
+ static enum test_return test_ascii_get(void)
1599
+ {
1600
+ execute(ascii_set_item("test_ascii_get", "value"));
1601
+
1602
+ execute(send_string("get\r\n"));
1603
+ execute(receive_error_response());
1604
+ execute(ascii_get_item("test_ascii_get", "value", true));
1605
+ execute(ascii_get_item("test_ascii_get_notfound", "value", false));
1606
+
1607
+ return TEST_PASS;
1608
+ }
1609
+
1610
+ static enum test_return test_ascii_gets(void)
1611
+ {
1612
+ execute(ascii_set_item("test_ascii_gets", "value"));
1613
+
1614
+ execute(send_string("gets\r\n"));
1615
+ execute(receive_error_response());
1616
+ unsigned long cas;
1617
+ execute(ascii_gets_item("test_ascii_gets", "value", true, &cas));
1618
+ execute(ascii_gets_item("test_ascii_gets_notfound", "value", false, &cas));
1619
+
1620
+ return TEST_PASS;
1621
+ }
1622
+
1623
+ static enum test_return test_ascii_mget(void)
1624
+ {
1625
+ const uint32_t nkeys= 5;
1626
+ const char * const keys[]= {
1627
+ "test_ascii_mget1",
1628
+ "test_ascii_mget2",
1629
+ /* test_ascii_mget_3 does not exist :) */
1630
+ "test_ascii_mget4",
1631
+ "test_ascii_mget5",
1632
+ "test_ascii_mget6"
1633
+ };
1634
+
1635
+ for (uint32_t x= 0; x < nkeys; ++x)
1636
+ execute(ascii_set_item(keys[x], "value"));
1637
+
1638
+ /* Ask for a key that doesn't exist as well */
1639
+ execute(send_string("get test_ascii_mget1 test_ascii_mget2 test_ascii_mget3 "
1640
+ "test_ascii_mget4 test_ascii_mget5 "
1641
+ "test_ascii_mget6\r\n"));
1642
+
1643
+ char *returned[nkeys];
1644
+
1645
+ for (uint32_t x= 0; x < nkeys; ++x)
1646
+ {
1647
+ ssize_t nbytes = 0;
1648
+ char *v= NULL;
1649
+ execute(ascii_get_unknown_value(&returned[x], &v, &nbytes));
1650
+ verify(nbytes == 5);
1651
+ verify(memcmp(v, "value", 5) == 0);
1652
+ free(v);
1653
+ }
1654
+
1655
+ char buffer[5];
1656
+ execute(retry_read(buffer, 5));
1657
+ verify(memcmp(buffer, "END\r\n", 5) == 0);
1658
+
1659
+ /* verify that we got all the keys we expected */
1660
+ for (uint32_t x= 0; x < nkeys; ++x)
1661
+ {
1662
+ bool found= false;
1663
+ for (uint32_t y= 0; y < nkeys; ++y)
1664
+ {
1665
+ if (strcmp(keys[x], returned[y]) == 0)
1666
+ {
1667
+ found = true;
1668
+ break;
1669
+ }
1670
+ }
1671
+ verify(found);
1672
+ }
1673
+
1674
+ for (uint32_t x= 0; x < nkeys; ++x)
1675
+ free(returned[x]);
1676
+
1677
+ return TEST_PASS;
1678
+ }
1679
+
1680
+ static enum test_return test_ascii_incr_impl(const char* key, bool noreply)
1681
+ {
1682
+ char cmd[300];
1683
+ snprintf(cmd, sizeof(cmd), "incr %s 1%s\r\n", key, noreply ? " noreply" : "");
1684
+
1685
+ execute(ascii_set_item(key, "0"));
1686
+ for (int x= 1; x < 11; ++x)
1687
+ {
1688
+ execute(send_string(cmd));
1689
+
1690
+ if (noreply)
1691
+ execute(test_ascii_version());
1692
+ else
1693
+ {
1694
+ char buffer[80];
1695
+ execute(receive_line(buffer, sizeof(buffer)));
1696
+ int val= atoi(buffer);
1697
+ verify(val == x);
1698
+ }
1699
+ }
1700
+
1701
+ execute(ascii_get_item(key, "10", true));
1702
+
1703
+ return TEST_PASS;
1704
+ }
1705
+
1706
+ static enum test_return test_ascii_incr(void)
1707
+ {
1708
+ return test_ascii_incr_impl("test_ascii_incr", false);
1709
+ }
1710
+
1711
+ static enum test_return test_ascii_incr_noreply(void)
1712
+ {
1713
+ return test_ascii_incr_impl("test_ascii_incr_noreply", true);
1714
+ }
1715
+
1716
+ static enum test_return test_ascii_decr_impl(const char* key, bool noreply)
1717
+ {
1718
+ char cmd[300];
1719
+ snprintf(cmd, sizeof(cmd), "decr %s 1%s\r\n", key, noreply ? " noreply" : "");
1720
+
1721
+ execute(ascii_set_item(key, "9"));
1722
+ for (int x= 8; x > -1; --x)
1723
+ {
1724
+ execute(send_string(cmd));
1725
+
1726
+ if (noreply)
1727
+ execute(test_ascii_version());
1728
+ else
1729
+ {
1730
+ char buffer[80];
1731
+ execute(receive_line(buffer, sizeof(buffer)));
1732
+ int val= atoi(buffer);
1733
+ verify(val == x);
1734
+ }
1735
+ }
1736
+
1737
+ execute(ascii_get_item(key, "0", true));
1738
+
1739
+ /* verify that it doesn't wrap */
1740
+ execute(send_string(cmd));
1741
+ if (noreply)
1742
+ execute(test_ascii_version());
1743
+ else
1744
+ {
1745
+ char buffer[80];
1746
+ execute(receive_line(buffer, sizeof(buffer)));
1747
+ }
1748
+ execute(ascii_get_item(key, "0", true));
1749
+
1750
+ return TEST_PASS;
1751
+ }
1752
+
1753
+ static enum test_return test_ascii_decr(void)
1754
+ {
1755
+ return test_ascii_decr_impl("test_ascii_decr", false);
1756
+ }
1757
+
1758
+ static enum test_return test_ascii_decr_noreply(void)
1759
+ {
1760
+ return test_ascii_decr_impl("test_ascii_decr_noreply", true);
1761
+ }
1762
+
1763
+
1764
+ static enum test_return test_ascii_flush_impl(const char *key, bool noreply)
1765
+ {
1766
+ #if 0
1767
+ /* Verify that the flush_all command handles unknown options */
1768
+ /* Bug in the current memcached server! */
1769
+ execute(send_string("flush_all foo bar\r\n"));
1770
+ execute(receive_error_response());
1771
+ #endif
1772
+
1773
+ execute(ascii_set_item(key, key));
1774
+ execute(ascii_get_item(key, key, true));
1775
+
1776
+ if (noreply)
1777
+ {
1778
+ execute(send_string("flush_all noreply\r\n"));
1779
+ execute(test_ascii_version());
1780
+ }
1781
+ else
1782
+ {
1783
+ execute(send_string("flush_all\r\n"));
1784
+ execute(receive_response("OK\r\n"));
1785
+ }
1786
+
1787
+ execute(ascii_get_item(key, key, false));
1788
+
1789
+ return TEST_PASS;
1790
+ }
1791
+
1792
+ static enum test_return test_ascii_flush(void)
1793
+ {
1794
+ return test_ascii_flush_impl("test_ascii_flush", false);
1795
+ }
1796
+
1797
+ static enum test_return test_ascii_flush_noreply(void)
1798
+ {
1799
+ return test_ascii_flush_impl("test_ascii_flush_noreply", true);
1800
+ }
1801
+
1802
+ static enum test_return test_ascii_concat_impl(const char *key,
1803
+ bool append,
1804
+ bool noreply)
1805
+ {
1806
+ const char *value;
1807
+
1808
+ if (append)
1809
+ value="hello";
1810
+ else
1811
+ value=" world";
1812
+
1813
+ execute(ascii_set_item(key, value));
1814
+
1815
+ if (append)
1816
+ value=" world";
1817
+ else
1818
+ value="hello";
1819
+
1820
+ char cmd[400];
1821
+ snprintf(cmd, sizeof(cmd), "%s %s 0 0 %u%s\r\n%s\r\n",
1822
+ append ? "append" : "prepend",
1823
+ key, (unsigned int)strlen(value), noreply ? " noreply" : "",
1824
+ value);
1825
+ execute(send_string(cmd));
1826
+
1827
+ if (noreply)
1828
+ execute(test_ascii_version());
1829
+ else
1830
+ execute(receive_response("STORED\r\n"));
1831
+
1832
+ execute(ascii_get_item(key, "hello world", true));
1833
+
1834
+ snprintf(cmd, sizeof(cmd), "%s %s_notfound 0 0 %u%s\r\n%s\r\n",
1835
+ append ? "append" : "prepend",
1836
+ key, (unsigned int)strlen(value), noreply ? " noreply" : "",
1837
+ value);
1838
+ execute(send_string(cmd));
1839
+
1840
+ if (noreply)
1841
+ execute(test_ascii_version());
1842
+ else
1843
+ execute(receive_response("NOT_STORED\r\n"));
1844
+
1845
+ return TEST_PASS;
1846
+ }
1847
+
1848
+ static enum test_return test_ascii_append(void)
1849
+ {
1850
+ return test_ascii_concat_impl("test_ascii_append", true, false);
1851
+ }
1852
+
1853
+ static enum test_return test_ascii_prepend(void)
1854
+ {
1855
+ return test_ascii_concat_impl("test_ascii_prepend", false, false);
1856
+ }
1857
+
1858
+ static enum test_return test_ascii_append_noreply(void)
1859
+ {
1860
+ return test_ascii_concat_impl("test_ascii_append_noreply", true, true);
1861
+ }
1862
+
1863
+ static enum test_return test_ascii_prepend_noreply(void)
1864
+ {
1865
+ return test_ascii_concat_impl("test_ascii_prepend_noreply", false, true);
1866
+ }
1867
+
1868
+ static enum test_return test_ascii_stat(void)
1869
+ {
1870
+ execute(send_string("stats noreply\r\n"));
1871
+ execute(receive_error_response());
1872
+ execute(send_string("stats\r\n"));
1873
+ char buffer[1024];
1874
+ do {
1875
+ execute(receive_line(buffer, sizeof(buffer)));
1876
+ } while (strcmp(buffer, "END\r\n") != 0);
1877
+
1878
+ return TEST_PASS_RECONNECT;
1879
+ }
1880
+
1881
+ typedef enum test_return(*TEST_FUNC)(void);
1882
+
1883
+ struct testcase
1884
+ {
1885
+ const char *description;
1886
+ TEST_FUNC function;
1887
+ };
1888
+
1889
+ struct testcase testcases[]= {
1890
+ { "ascii quit", test_ascii_quit },
1891
+ { "ascii version", test_ascii_version },
1892
+ { "ascii verbosity", test_ascii_verbosity },
1893
+ { "ascii set", test_ascii_set },
1894
+ { "ascii set noreply", test_ascii_set_noreply },
1895
+ { "ascii get", test_ascii_get },
1896
+ { "ascii gets", test_ascii_gets },
1897
+ { "ascii mget", test_ascii_mget },
1898
+ { "ascii flush", test_ascii_flush },
1899
+ { "ascii flush noreply", test_ascii_flush_noreply },
1900
+ { "ascii add", test_ascii_add },
1901
+ { "ascii add noreply", test_ascii_add_noreply },
1902
+ { "ascii replace", test_ascii_replace },
1903
+ { "ascii replace noreply", test_ascii_replace_noreply },
1904
+ { "ascii cas", test_ascii_cas },
1905
+ { "ascii cas noreply", test_ascii_cas_noreply },
1906
+ { "ascii delete", test_ascii_delete },
1907
+ { "ascii delete noreply", test_ascii_delete_noreply },
1908
+ { "ascii incr", test_ascii_incr },
1909
+ { "ascii incr noreply", test_ascii_incr_noreply },
1910
+ { "ascii decr", test_ascii_decr },
1911
+ { "ascii decr noreply", test_ascii_decr_noreply },
1912
+ { "ascii append", test_ascii_append },
1913
+ { "ascii append noreply", test_ascii_append_noreply },
1914
+ { "ascii prepend", test_ascii_prepend },
1915
+ { "ascii prepend noreply", test_ascii_prepend_noreply },
1916
+ { "ascii stat", test_ascii_stat },
1917
+ { "binary noop", test_binary_noop },
1918
+ { "binary quit", test_binary_quit },
1919
+ { "binary quitq", test_binary_quitq },
1920
+ { "binary set", test_binary_set },
1921
+ { "binary setq", test_binary_setq },
1922
+ { "binary flush", test_binary_flush },
1923
+ { "binary flushq", test_binary_flushq },
1924
+ { "binary add", test_binary_add },
1925
+ { "binary addq", test_binary_addq },
1926
+ { "binary replace", test_binary_replace },
1927
+ { "binary replaceq", test_binary_replaceq },
1928
+ { "binary delete", test_binary_delete },
1929
+ { "binary deleteq", test_binary_deleteq },
1930
+ { "binary get", test_binary_get },
1931
+ { "binary getq", test_binary_getq },
1932
+ { "binary getk", test_binary_getk },
1933
+ { "binary getkq", test_binary_getkq },
1934
+ { "binary incr", test_binary_incr },
1935
+ { "binary incrq", test_binary_incrq },
1936
+ { "binary decr", test_binary_decr },
1937
+ { "binary decrq", test_binary_decrq },
1938
+ { "binary version", test_binary_version },
1939
+ { "binary append", test_binary_append },
1940
+ { "binary appendq", test_binary_appendq },
1941
+ { "binary prepend", test_binary_prepend },
1942
+ { "binary prependq", test_binary_prependq },
1943
+ { "binary stat", test_binary_stat },
1944
+ { NULL, NULL}
1945
+ };
1946
+
1947
+ const int ascii_tests = 1;
1948
+ const int binary_tests = 2;
1949
+
1950
+ struct test_type_st
1951
+ {
1952
+ bool ascii;
1953
+ bool binary;
1954
+ };
1955
+
1956
+ int main(int argc, char **argv)
1957
+ {
1958
+ static const char * const status_msg[]= {"[skip]", "[pass]", "[pass]", "[FAIL]"};
1959
+ struct test_type_st tests= { true, true };
1960
+ int total= 0;
1961
+ int failed= 0;
1962
+ const char *hostname= "localhost";
1963
+ const char *port= "11211";
1964
+ int cmd;
1965
+ bool prompt= false;
1966
+ const char *testname= NULL;
1967
+
1968
+
1969
+
1970
+ while ((cmd= getopt(argc, argv, "t:vch:p:PT:?ab")) != EOF)
1971
+ {
1972
+ switch (cmd) {
1973
+ case 'a':
1974
+ tests.ascii= true;
1975
+ tests.binary= false;
1976
+ break;
1977
+ case 'b':
1978
+ tests.ascii= false;
1979
+ tests.binary= true;
1980
+ break;
1981
+ case 't':
1982
+ timeout= atoi(optarg);
1983
+ if (timeout == 0)
1984
+ {
1985
+ fprintf(stderr, "Invalid timeout. Please specify a number for -t\n");
1986
+ return EXIT_FAILURE;
1987
+ }
1988
+ break;
1989
+ case 'v': verbose= true;
1990
+ break;
1991
+ case 'c': do_core= true;
1992
+ break;
1993
+ case 'h': hostname= optarg;
1994
+ break;
1995
+ case 'p': port= optarg;
1996
+ break;
1997
+ case 'P': prompt= true;
1998
+ break;
1999
+ case 'T': testname= optarg;
2000
+ break;
2001
+ default:
2002
+ fprintf(stderr, "Usage: %s [-h hostname] [-p port] [-c] [-v] [-t n] [-P] [-T testname]'\n"
2003
+ "\t-c\tGenerate coredump if a test fails\n"
2004
+ "\t-v\tVerbose test output (print out the assertion)\n"
2005
+ "\t-t n\tSet the timeout for io-operations to n seconds\n"
2006
+ "\t-P\tPrompt the user before starting a test.\n"
2007
+ "\t\t\t\"skip\" will skip the test\n"
2008
+ "\t\t\t\"quit\" will terminate memcapable\n"
2009
+ "\t\t\tEverything else will start the test\n"
2010
+ "\t-T n\tJust run the test named n\n"
2011
+ "\t-a\tOnly test the ascii protocol\n"
2012
+ "\t-b\tOnly test the binary protocol\n",
2013
+ argv[0]);
2014
+ return EXIT_FAILURE;
2015
+ }
2016
+ }
2017
+
2018
+ initialize_sockets();
2019
+ sock= connect_server(hostname, port);
2020
+ if (sock == INVALID_SOCKET)
2021
+ {
2022
+ fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
2023
+ hostname, port, strerror(get_socket_errno()));
2024
+ return EXIT_FAILURE;
2025
+ }
2026
+
2027
+ for (int ii= 0; testcases[ii].description != NULL; ++ii)
2028
+ {
2029
+ if (testname != NULL && strcmp(testcases[ii].description, testname) != 0)
2030
+ continue;
2031
+
2032
+ if ((testcases[ii].description[0] == 'a' && (tests.ascii) == 0) ||
2033
+ (testcases[ii].description[0] == 'b' && (tests.binary) == 0))
2034
+ {
2035
+ continue;
2036
+ }
2037
+ ++total;
2038
+ fprintf(stdout, "%-40s", testcases[ii].description);
2039
+ fflush(stdout);
2040
+
2041
+ if (prompt)
2042
+ {
2043
+ fprintf(stdout, "\nPress <return> when you are ready? ");
2044
+ char buffer[80] = {0};
2045
+ if (fgets(buffer, sizeof(buffer), stdin) != NULL) {
2046
+ if (strncmp(buffer, "skip", 4) == 0)
2047
+ {
2048
+ fprintf(stdout, "%-40s%s\n", testcases[ii].description,
2049
+ status_msg[TEST_SKIP]);
2050
+ fflush(stdout);
2051
+ continue;
2052
+ }
2053
+ if (strncmp(buffer, "quit", 4) == 0)
2054
+ exit(0);
2055
+ }
2056
+
2057
+ fprintf(stdout, "%-40s", testcases[ii].description);
2058
+ fflush(stdout);
2059
+ }
2060
+
2061
+ bool reconnect= false;
2062
+ enum test_return ret= testcases[ii].function();
2063
+ if (ret == TEST_FAIL)
2064
+ {
2065
+ reconnect= true;
2066
+ ++failed;
2067
+ if (verbose)
2068
+ fprintf(stderr, "\n");
2069
+ }
2070
+ else if (ret == TEST_PASS_RECONNECT)
2071
+ reconnect= true;
2072
+
2073
+ fprintf(stderr, "%s\n", status_msg[ret]);
2074
+ if (reconnect)
2075
+ {
2076
+ closesocket(sock);
2077
+ if ((sock= connect_server(hostname, port)) == INVALID_SOCKET)
2078
+ {
2079
+ fprintf(stderr, "Failed to connect to <%s:%s>: %s\n",
2080
+ hostname, port, strerror(get_socket_errno()));
2081
+ fprintf(stderr, "%d of %d tests failed\n", failed, total);
2082
+ return EXIT_FAILURE;
2083
+ }
2084
+ }
2085
+ }
2086
+
2087
+ closesocket(sock);
2088
+ if (failed == 0)
2089
+ fprintf(stdout, "All tests passed\n");
2090
+ else
2091
+ fprintf(stderr, "%d of %d tests failed\n", failed, total);
2092
+
2093
+ return (failed == 0) ? 0 : 1;
2094
+ }