couchbase-memcached 1.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }