libcouchbase 1.0.4 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +11 -8
  3. data/ext/libcouchbase/CMakeLists.txt +1 -1
  4. data/ext/libcouchbase/README.markdown +38 -6
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +151 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -2
  7. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  8. data/ext/libcouchbase/cmake/source_files.cmake +1 -0
  9. data/ext/libcouchbase/contrib/cJSON/cJSON.c +686 -288
  10. data/ext/libcouchbase/contrib/cJSON/cJSON.h +0 -0
  11. data/ext/libcouchbase/contrib/cbsasl/src/hash.c +17 -17
  12. data/ext/libcouchbase/contrib/cliopts/cliopts.c +76 -0
  13. data/ext/libcouchbase/contrib/cliopts/cliopts.h +66 -15
  14. data/ext/libcouchbase/contrib/genhash/genhash.c +1 -2
  15. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4 -3
  16. data/ext/libcouchbase/example/instancepool/main.cc +12 -2
  17. data/ext/libcouchbase/example/libeventdirect/main.c +99 -25
  18. data/ext/libcouchbase/example/minimal/minimal.c +7 -5
  19. data/ext/libcouchbase/example/observe/durability.c +102 -0
  20. data/ext/libcouchbase/example/observe/observe.c +19 -6
  21. data/ext/libcouchbase/example/subdoc/subdoc-xattrs.c +1 -2
  22. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +6 -8
  23. data/ext/libcouchbase/include/libcouchbase/cntl.h +84 -64
  24. data/ext/libcouchbase/include/libcouchbase/couchbase.h +295 -78
  25. data/ext/libcouchbase/include/libcouchbase/deprecated.h +2 -2
  26. data/ext/libcouchbase/include/libcouchbase/error.h +1 -1
  27. data/ext/libcouchbase/include/libcouchbase/iops.h +9 -9
  28. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +2 -2
  29. data/ext/libcouchbase/include/libcouchbase/n1ql.h +69 -7
  30. data/ext/libcouchbase/include/libcouchbase/vbucket.h +17 -0
  31. data/ext/libcouchbase/include/libcouchbase/views.h +3 -3
  32. data/ext/libcouchbase/include/memcached/protocol_binary.h +62 -1
  33. data/ext/libcouchbase/packaging/deb/control +1 -1
  34. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +37 -36
  35. data/ext/libcouchbase/src/bootstrap.cc +22 -8
  36. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +1 -1
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +0 -1
  38. data/ext/libcouchbase/src/bucketconfig/confmon.cc +13 -8
  39. data/ext/libcouchbase/src/callbacks.c +2 -0
  40. data/ext/libcouchbase/src/cntl.cc +28 -17
  41. data/ext/libcouchbase/src/dns-srv.cc +1 -2
  42. data/ext/libcouchbase/src/dump.cc +4 -0
  43. data/ext/libcouchbase/src/errmap.h +89 -16
  44. data/ext/libcouchbase/src/handler.cc +28 -11
  45. data/ext/libcouchbase/src/http/http-priv.h +4 -1
  46. data/ext/libcouchbase/src/http/http.cc +3 -0
  47. data/ext/libcouchbase/src/instance.cc +1 -1
  48. data/ext/libcouchbase/src/internal.h +1 -0
  49. data/ext/libcouchbase/src/lcbio/connect.cc +2 -3
  50. data/ext/libcouchbase/src/lcbio/manager.cc +2 -2
  51. data/ext/libcouchbase/src/lcbio/ssl.h +10 -0
  52. data/ext/libcouchbase/src/mc/mcreq.c +8 -0
  53. data/ext/libcouchbase/src/mcserver/mcserver.cc +14 -1
  54. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +0 -3
  55. data/ext/libcouchbase/src/n1ql/n1ql.cc +22 -29
  56. data/ext/libcouchbase/src/n1ql/params.cc +46 -1
  57. data/ext/libcouchbase/src/newconfig.cc +4 -4
  58. data/ext/libcouchbase/src/operations/durability-seqno.cc +4 -0
  59. data/ext/libcouchbase/src/operations/durability.cc +3 -0
  60. data/ext/libcouchbase/src/operations/ping.cc +315 -0
  61. data/ext/libcouchbase/src/operations/stats.cc +10 -0
  62. data/ext/libcouchbase/src/operations/subdoc.cc +13 -1
  63. data/ext/libcouchbase/src/retrychk.cc +1 -0
  64. data/ext/libcouchbase/src/settings.c +2 -0
  65. data/ext/libcouchbase/src/settings.h +13 -7
  66. data/ext/libcouchbase/src/ssl/ssl_c.c +28 -2
  67. data/ext/libcouchbase/src/ssl/ssl_common.c +3 -0
  68. data/ext/libcouchbase/src/ssl/ssl_e.c +15 -1
  69. data/ext/libcouchbase/src/ssl/ssl_iot_common.h +3 -1
  70. data/ext/libcouchbase/src/timings.c +0 -1
  71. data/ext/libcouchbase/src/vbucket/vbucket.c +49 -1
  72. data/ext/libcouchbase/tests/iotests/mock-environment.cc +58 -40
  73. data/ext/libcouchbase/tests/iotests/mock-environment.h +23 -4
  74. data/ext/libcouchbase/tests/iotests/mock-unit-test.h +8 -8
  75. data/ext/libcouchbase/tests/iotests/t_behavior.cc +5 -5
  76. data/ext/libcouchbase/tests/iotests/t_durability.cc +50 -0
  77. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +4 -2
  78. data/ext/libcouchbase/tests/iotests/t_errmap.cc +6 -3
  79. data/ext/libcouchbase/tests/iotests/t_lock.cc +5 -6
  80. data/ext/libcouchbase/tests/iotests/t_misc.cc +44 -0
  81. data/ext/libcouchbase/tests/iotests/t_serverops.cc +1 -0
  82. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +28 -0
  83. data/ext/libcouchbase/tests/iotests/t_views.cc +22 -10
  84. data/ext/libcouchbase/tools/CMakeLists.txt +21 -1
  85. data/ext/libcouchbase/tools/cbc-handlers.h +23 -3
  86. data/ext/libcouchbase/tools/cbc-n1qlback.cc +1 -1
  87. data/ext/libcouchbase/tools/cbc-pillowfight.cc +126 -26
  88. data/ext/libcouchbase/tools/cbc-proxy.cc +403 -0
  89. data/ext/libcouchbase/tools/cbc-subdoc.cc +826 -0
  90. data/ext/libcouchbase/tools/cbc.cc +149 -37
  91. data/ext/libcouchbase/tools/common/options.h +5 -2
  92. data/ext/libcouchbase/tools/linenoise/linenoise.c +15 -15
  93. data/lib/libcouchbase.rb +4 -0
  94. data/lib/libcouchbase/bucket.rb +51 -0
  95. data/lib/libcouchbase/connection.rb +100 -13
  96. data/lib/libcouchbase/ext/libcouchbase.rb +40 -0
  97. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +13 -1
  98. data/lib/libcouchbase/ext/libcouchbase/enums.rb +2 -1
  99. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +5 -0
  100. data/lib/libcouchbase/subdoc_request.rb +129 -0
  101. data/lib/libcouchbase/version.rb +1 -1
  102. data/spec/bucket_spec.rb +15 -1
  103. data/spec/connection_spec.rb +1 -1
  104. data/spec/subdoc_spec.rb +192 -0
  105. metadata +13 -4
  106. data/ext/libcouchbase/.travis.yml +0 -19
@@ -225,8 +225,11 @@ class MockEnvironment : public ::testing::Environment
225
225
  public:
226
226
  enum ServerVersion {
227
227
  VERSION_UNKNOWN = 0,
228
- VERSION_10 = 1,
229
- VERSION_20 = 2
228
+ VERSION_40 = 4,
229
+ VERSION_41 = 5,
230
+ VERSION_45 = 6,
231
+ VERSION_46 = 7,
232
+ VERSION_50 = 8
230
233
  };
231
234
 
232
235
  virtual void SetUp();
@@ -273,7 +276,7 @@ public:
273
276
  * @param index the index of the node on the mock
274
277
  * @param bucket the name of the bucket
275
278
  */
276
- void failoverNode(int index, std::string bucket = "default");
279
+ void failoverNode(int index, std::string bucket = "default", bool rebalance = true);
277
280
 
278
281
  /**
279
282
  * Simulate node reconvering. In this case mock will enable server
@@ -373,7 +376,7 @@ public:
373
376
 
374
377
  static void printSkipMessage(std::string file, int line, std::string reason) {
375
378
  std::cerr << "Skipping " << file << ":" << std::dec << line;
376
- std::cerr << "(" << reason << ")";
379
+ std::cerr << " (" << reason << ")";
377
380
  std::cerr << std::endl;
378
381
  }
379
382
 
@@ -431,5 +434,21 @@ private:
431
434
  return; \
432
435
  }
433
436
 
437
+ #define CLUSTER_VERSION_IS_HIGHER_THAN(v) \
438
+ (MockEnvironment::getInstance()->isRealCluster() && MockEnvironment::getInstance()->getServerVersion() >= v)
434
439
 
440
+ #define SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(v) \
441
+ if (CLUSTER_VERSION_IS_HIGHER_THAN(v)) { \
442
+ MockEnvironment::printSkipMessage(__FILE__, __LINE__, "needs lower cluster version"); \
443
+ return; \
444
+ }
445
+
446
+ #define CLUSTER_VERSION_IS_LOWER_THAN(v) \
447
+ (MockEnvironment::getInstance()->isRealCluster() && MockEnvironment::getInstance()->getServerVersion() < v)
448
+
449
+ #define SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(v) \
450
+ if (CLUSTER_VERSION_IS_LOWER_THAN(v)) { \
451
+ MockEnvironment::printSkipMessage(__FILE__, __LINE__, "needs higher cluster version"); \
452
+ return; \
453
+ }
435
454
  #endif
@@ -24,16 +24,16 @@
24
24
 
25
25
  class HandleWrap;
26
26
 
27
- #define SKIP_IF_MOCK() \
28
- if (!getenv(LCB_TEST_REALCLUSTER_ENV)) { \
29
- std::cerr << "Skipping: Need real cluster\n" << std::endl; \
30
- return; \
27
+ #define SKIP_IF_MOCK() \
28
+ if (!getenv(LCB_TEST_REALCLUSTER_ENV)) { \
29
+ MockEnvironment::printSkipMessage(__FILE__, __LINE__, "needs real cluster"); \
30
+ return; \
31
31
  }
32
32
 
33
- #define SKIP_UNLESS_MOCK() \
34
- if (getenv(LCB_TEST_REALCLUSTER_ENV)) { \
35
- std::cerr << "Skipping: Need mock cluster\n" << std::endl; \
36
- return; \
33
+ #define SKIP_UNLESS_MOCK() \
34
+ if (getenv(LCB_TEST_REALCLUSTER_ENV)) { \
35
+ MockEnvironment::printSkipMessage(__FILE__, __LINE__, "needs mock cluster"); \
36
+ return; \
37
37
  }
38
38
 
39
39
  #define ASSERT_ERRISA(err, et) \
@@ -201,20 +201,20 @@ TEST_F(Behavior, BadPluginEnvironment)
201
201
  setPluginEnv("foobarbaz", "non_existent_symbol");
202
202
  err = lcb_cntl(NULL, LCB_CNTL_GET, LCB_CNTL_IOPS_DEFAULT_TYPES, &info);
203
203
  ASSERT_EQ(LCB_SUCCESS, err);
204
- ASSERT_EQ(info.v.v0.os_default, EXPECTED_DEFAULT);
205
- ASSERT_EQ(info.v.v0.effective, 0);
204
+ ASSERT_EQ(EXPECTED_DEFAULT, info.v.v0.os_default);
205
+ ASSERT_EQ(0, info.v.v0.effective);
206
206
 
207
207
  lcb_t instance2;
208
- ASSERT_EQ(lcb_create(&instance2, NULL), LCB_DLOPEN_FAILED);
208
+ ASSERT_EQ(LCB_DLOPEN_FAILED, lcb_create(&instance2, NULL));
209
209
 
210
210
  setPluginEnv("foobarbaz", "");
211
- ASSERT_EQ(lcb_create(&instance2, NULL), LCB_BAD_ENVIRONMENT);
211
+ ASSERT_EQ(LCB_BAD_ENVIRONMENT, lcb_create(&instance2, NULL));
212
212
 
213
213
  // Find a DLL that we know can be loaded, but doesn't have the symbols
214
214
  // we need. For windows, we use the unqualified name,
215
215
  const char *dllname = TEST_SHARED_OBJECT;
216
216
 
217
217
  setPluginEnv(dllname, "nonexist-symbol");
218
- ASSERT_EQ(lcb_create(&instance2, NULL), LCB_DLSYM_FAILED);
218
+ ASSERT_EQ(LCB_DLSYM_FAILED, lcb_create(&instance2, NULL));
219
219
 
220
220
  }
@@ -1056,3 +1056,53 @@ TEST_F(DurabilityUnitTest, testDurStore)
1056
1056
  lcb_log(LOGARGS(instance, WARN), "Test skipped because mock is too fast(!)");
1057
1057
  }
1058
1058
  }
1059
+
1060
+ TEST_F(DurabilityUnitTest, testFailoverAndSeqno)
1061
+ {
1062
+ SKIP_UNLESS_MOCK();
1063
+
1064
+ // Disable CCCP so that we get streaming updates
1065
+ MockEnvironment *mock = MockEnvironment::getInstance();
1066
+ mock->setCCCP(false);
1067
+
1068
+ HandleWrap hwrap;
1069
+ lcb_t instance;
1070
+ lcb_durability_opts_t opts = { 0 };
1071
+ string key = "key-failover-seqno";
1072
+ Item itm = Item(key, key);
1073
+ KVOperation kvo(&itm);
1074
+
1075
+ createConnection(hwrap);
1076
+ instance = hwrap.getLcb();
1077
+
1078
+ kvo.store(instance);
1079
+
1080
+ defaultOptions(instance, opts);
1081
+ DurabilityOperation dop;
1082
+
1083
+ /* make sure that seqno works on healthy cluster */
1084
+ opts.version = 1;
1085
+ opts.v.v0.pollopts = LCB_DURABILITY_MODE_SEQNO;
1086
+ dop = DurabilityOperation();
1087
+ dop.run(instance, &opts, kvo.result);
1088
+ ASSERT_EQ(LCB_SUCCESS, dop.resp.rc);
1089
+
1090
+ /* failover all nodes but master */
1091
+ lcbvb_CONFIG *vbc;
1092
+ ASSERT_EQ(LCB_SUCCESS, lcb_cntl(instance, LCB_CNTL_GET, LCB_CNTL_VBCONFIG, &vbc));
1093
+ int vbid, srvix;
1094
+ lcbvb_map_key(vbc, key.c_str(), key.size(), &vbid, &srvix);
1095
+ for (size_t jj = 0; jj < lcbvb_get_nreplicas(vbc); jj++) {
1096
+ int rix = lcbvb_vbreplica(vbc, vbid, jj);
1097
+ mock->failoverNode(rix, "default", false);
1098
+ }
1099
+
1100
+ /* make sure that client gets new configration */
1101
+ instance->bs_state->reset_last_refresh();
1102
+ instance->confmon->stop();
1103
+ instance->bootstrap(lcb::BS_REFRESH_ALWAYS);
1104
+
1105
+ dop = DurabilityOperation();
1106
+ dop.run(instance, &opts, kvo.result);
1107
+ ASSERT_EQ(LCB_DURABILITY_ETOOMANY, dop.resp.rc);
1108
+ }
@@ -22,8 +22,10 @@ protected:
22
22
  void checkRetryVerify(uint16_t errcode);
23
23
 
24
24
  void TearDown() {
25
- MockOpFailClearCommand clearCmd(MockEnvironment::getInstance()->getNumNodes());
26
- doMockTxn(clearCmd);
25
+ if (!MockEnvironment::getInstance()->isRealCluster()) {
26
+ MockOpFailClearCommand clearCmd(MockEnvironment::getInstance()->getNumNodes());
27
+ doMockTxn(clearCmd);
28
+ }
27
29
  MockUnitTest::TearDown();
28
30
  }
29
31
  };
@@ -16,8 +16,10 @@ protected:
16
16
  void checkRetryVerify(uint16_t errcode);
17
17
 
18
18
  void TearDown() {
19
- MockOpFailClearCommand clearCmd(MockEnvironment::getInstance()->getNumNodes());
20
- doMockTxn(clearCmd);
19
+ if (!MockEnvironment::getInstance()->isRealCluster()) {
20
+ MockOpFailClearCommand clearCmd(MockEnvironment::getInstance()->getNumNodes());
21
+ doMockTxn(clearCmd);
22
+ }
21
23
  MockUnitTest::TearDown();
22
24
  }
23
25
  };
@@ -152,7 +154,7 @@ void ErrmapUnitTest::checkRetryVerify(uint16_t errcode) {
152
154
  #ifdef __APPLE__
153
155
  // FIXME: on Jenkins OSX actual expected time does not match actual and mock raises exception like following:
154
156
  // VerificationException: Not enough/too many retries. Last TS=1498594892704. Last expected=1498594892728. Diff=24. MaxDiff=20
155
- verifyCmd.set("fuzz_ms", 25);
157
+ verifyCmd.set("fuzz_ms", 35);
156
158
  #else
157
159
  verifyCmd.set("fuzz_ms", 20);
158
160
  #endif
@@ -174,5 +176,6 @@ TEST_F(ErrmapUnitTest, retrySpecLinear) {
174
176
  }
175
177
 
176
178
  TEST_F(ErrmapUnitTest, retrySpecExponential) {
179
+ SKIP_UNLESS_MOCK();
177
180
  checkRetryVerify(ERRCODE_EXPONENTIAL);
178
181
  }
@@ -122,12 +122,11 @@ TEST_F(LockUnitTest, testUnlockMissingCas)
122
122
  err = lcb_unlock(instance, &reserr, 1, &cmdlist);
123
123
  ASSERT_EQ(LCB_SUCCESS, err);
124
124
  lcb_wait(instance);
125
-
126
- /**
127
- * maybe I mis-understood lock, but isn't it an error to use unlock
128
- * without a valid CAS? -
129
- */
130
- ASSERT_EQ(LCB_ETMPFAIL, reserr);
125
+ if (CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_50)) {
126
+ ASSERT_EQ(LCB_EINVAL_MCD, reserr);
127
+ } else {
128
+ ASSERT_EQ(LCB_ETMPFAIL, reserr);
129
+ }
131
130
  }
132
131
 
133
132
  extern "C" {
@@ -715,6 +715,7 @@ TEST_F(MockUnitTest, testEmptyCtx)
715
715
 
716
716
  TEST_F(MockUnitTest, testMultiCreds)
717
717
  {
718
+ SKIP_IF_CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_50);
718
719
  using lcb::Authenticator;
719
720
 
720
721
  HandleWrap hw;
@@ -731,3 +732,46 @@ TEST_F(MockUnitTest, testMultiCreds)
731
732
  ASSERT_NE(auth.buckets().end(), res);
732
733
  ASSERT_EQ("secret", res->second);
733
734
  }
735
+
736
+ extern "C" {
737
+ static void appendE2BIGcb(lcb_t, int, const lcb_RESPBASE *rb)
738
+ {
739
+ lcb_error_t *e = (lcb_error_t *)rb->cookie;
740
+ *e = rb->rc;
741
+ }
742
+ }
743
+
744
+ TEST_F(MockUnitTest, testAppendE2BIG)
745
+ {
746
+ HandleWrap hw;
747
+ lcb_t instance;
748
+ createConnection(hw, instance);
749
+ lcb_install_callback3(instance, LCB_CALLBACK_STORE, appendE2BIGcb);
750
+
751
+ lcb_error_t err, res;
752
+
753
+ const char *key = "key";
754
+ size_t nkey = strlen(key);
755
+
756
+ size_t nvalue1 = 20 * 1024 * 1024;
757
+ void *value1 = malloc(nvalue1);
758
+ lcb_CMDSTORE scmd = { 0 };
759
+ scmd.operation = LCB_SET;
760
+ LCB_CMD_SET_KEY(&scmd, key, nkey);
761
+ LCB_CMD_SET_VALUE(&scmd, value1, nvalue1);
762
+ err = lcb_store3(instance, &res, &scmd);
763
+ lcb_wait(instance);
764
+ ASSERT_EQ(LCB_SUCCESS, res);
765
+ free(value1);
766
+
767
+ size_t nvalue2 = 1 * 1024 * 1024;
768
+ void *value2 = malloc(nvalue2);
769
+ lcb_CMDSTORE acmd = { 0 };
770
+ acmd.operation = LCB_APPEND;
771
+ LCB_CMD_SET_KEY(&acmd, key, nkey);
772
+ LCB_CMD_SET_VALUE(&acmd, value2, nvalue2);
773
+ err = lcb_store3(instance, &res, &acmd);
774
+ lcb_wait(instance);
775
+ ASSERT_EQ(LCB_E2BIG, res);
776
+ free(value2);
777
+ }
@@ -148,6 +148,7 @@ extern "C" {
148
148
  */
149
149
  TEST_F(ServeropsUnitTest, testFlush)
150
150
  {
151
+ SKIP_UNLESS_MOCK();
151
152
  lcb_t instance;
152
153
  HandleWrap hw;
153
154
  createConnection(hw, instance);
@@ -295,6 +295,7 @@ verifyPathValue(const char *, const char *, const char *, const char *,
295
295
 
296
296
  TEST_F(SubdocUnitTest, testSdGetExists)
297
297
  {
298
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_45);
298
299
  HandleWrap hw;
299
300
  lcb_t instance;
300
301
  CREATE_SUBDOC_CONNECTION(hw, instance);
@@ -400,6 +401,7 @@ TEST_F(SubdocUnitTest, testSdGetExists)
400
401
 
401
402
  TEST_F(SubdocUnitTest, testSdStore)
402
403
  {
404
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_45);
403
405
  HandleWrap hw;
404
406
  lcb_t instance;
405
407
  CREATE_SUBDOC_CONNECTION(hw, instance);
@@ -490,6 +492,7 @@ TEST_F(SubdocUnitTest, testSdStore)
490
492
  }
491
493
 
492
494
  TEST_F(SubdocUnitTest, testMkdoc) {
495
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_50);
493
496
  HandleWrap hw;
494
497
  lcb_t instance;
495
498
  lcb_CMDSUBDOC cmd = { 0 };
@@ -527,6 +530,7 @@ TEST_F(SubdocUnitTest, testMkdoc) {
527
530
 
528
531
  TEST_F(SubdocUnitTest, testUnique)
529
532
  {
533
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_45);
530
534
  HandleWrap hw;
531
535
  lcb_t instance;
532
536
  lcb_CMDSUBDOC cmd = { 0 };
@@ -577,6 +581,7 @@ TEST_F(SubdocUnitTest, testUnique)
577
581
 
578
582
  TEST_F(SubdocUnitTest, testCounter)
579
583
  {
584
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_45);
580
585
  HandleWrap hw;
581
586
  lcb_t instance;
582
587
  lcb_CMDSUBDOC cmd = { 0 };
@@ -610,6 +615,12 @@ TEST_F(SubdocUnitTest, testCounter)
610
615
  spec.sdcmd = LCB_SDCMD_COUNTER;
611
616
  LCB_SDSPEC_SET_VALUE(&spec, "1", 1);
612
617
  ASSERT_EQ(LCB_SUCCESS, schedwait(instance, &res, &cmd, lcb_subdoc3));
618
+ ASSERT_SD_ERR(res, LCB_SUBDOC_VALUE_CANTINSERT);
619
+
620
+ // Try to increment by 0
621
+ spec.sdcmd = LCB_SDCMD_COUNTER;
622
+ LCB_SDSPEC_SET_VALUE(&spec, "0", 1);
623
+ ASSERT_EQ(LCB_SUCCESS, schedwait(instance, &res, &cmd, lcb_subdoc3));
613
624
  ASSERT_SD_ERR(res, LCB_SUBDOC_BAD_DELTA);
614
625
 
615
626
  // Try to use an already large number (so the number is too big on the server)
@@ -653,6 +664,7 @@ TEST_F(SubdocUnitTest, testCounter)
653
664
 
654
665
  TEST_F(SubdocUnitTest, testMultiLookup)
655
666
  {
667
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_45);
656
668
  HandleWrap hw;
657
669
  lcb_t instance;
658
670
  CREATE_SUBDOC_CONNECTION(hw, instance);
@@ -724,6 +736,7 @@ TEST_F(SubdocUnitTest, testMultiLookup)
724
736
 
725
737
  TEST_F(SubdocUnitTest, testMultiMutations)
726
738
  {
739
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_45);
727
740
  HandleWrap hw;
728
741
  lcb_t instance;
729
742
  CREATE_SUBDOC_CONNECTION(hw, instance);
@@ -789,9 +802,24 @@ TEST_F(SubdocUnitTest, testMultiMutations)
789
802
  ASSERT_EQ(1, mr.size());
790
803
  ASSERT_EQ(LCB_SUBDOC_PATH_ENOENT, mr.results[0].rc);
791
804
  ASSERT_EQ(1, mr.results[0].index);
805
+
806
+ /* check if lcb_subdoc3 can detect mutation, and allow setting exptime */
807
+ specs.clear();
808
+ mcmd.multimode = 0;
809
+ mcmd.exptime = 42;
810
+
811
+ LCB_SDSPEC_INIT(&spec, LCB_SDCMD_DICT_UPSERT, "tmpPath", strlen("tmpPath"), "null", 4);
812
+ specs.push_back(spec);
813
+ mcmd.specs = &specs[0];
814
+ mcmd.nspecs = specs.size();
815
+ ASSERT_EQ(LCB_SUCCESS, schedwait(instance, &mr, &mcmd, lcb_subdoc3));
816
+ ASSERT_EQ(LCB_SUCCESS, mr.rc);
817
+ ASSERT_EQ(1, mr.size());
818
+ ASSERT_EQ(LCB_SUCCESS, mr.results[0].rc);
792
819
  }
793
820
 
794
821
  TEST_F(SubdocUnitTest, testGetCount) {
822
+ SKIP_IF_CLUSTER_VERSION_IS_LOWER_THAN(MockEnvironment::VERSION_50);
795
823
  HandleWrap hw;
796
824
  lcb_t instance;
797
825
  lcb_CMDSUBDOC cmd = { 0 };
@@ -34,14 +34,15 @@ ViewsUnitTest::connectBeerSample(HandleWrap& hw, lcb_t& instance, bool first)
34
34
  MockEnvironment::getInstance()->makeConnectParams(crparams, NULL);
35
35
  crparamsAdmin = crparams;
36
36
 
37
- // We could do CCCP if we really cared.. but it's simpler and makes
38
- // the logs cleaner.
39
37
  crparams.v.v2.bucket = "beer-sample";
40
- crparams.v.v2.user = "beer-sample";
41
- crparams.v.v2.mchosts = NULL;
42
- lcb_config_transport_t transports[] = {
43
- LCB_CONFIG_TRANSPORT_HTTP, LCB_CONFIG_TRANSPORT_LIST_END };
44
- crparams.v.v2.transports = transports;
38
+ if (!CLUSTER_VERSION_IS_HIGHER_THAN(MockEnvironment::VERSION_50)) {
39
+ // We could do CCCP if we really cared.. but it's simpler and makes
40
+ // the logs cleaner.
41
+ crparams.v.v2.user = "beer-sample";
42
+ crparams.v.v2.mchosts = NULL;
43
+ lcb_config_transport_t transports[] = {LCB_CONFIG_TRANSPORT_HTTP, LCB_CONFIG_TRANSPORT_LIST_END};
44
+ crparams.v.v2.transports = transports;
45
+ }
45
46
 
46
47
  // See if we can connect:
47
48
  lcb_error_t rv = tryCreateConnection(hw, instance, crparams);
@@ -147,8 +148,12 @@ struct ViewInfo {
147
148
  cJSON *cj = cJSON_Parse(resp->value);
148
149
  ASSERT_FALSE(cj == NULL);
149
150
  cJSON *jTotal = cJSON_GetObjectItem(cj, "total_rows");
150
- ASSERT_FALSE(jTotal == NULL);
151
- totalRows = jTotal->valueint;
151
+ if (jTotal != NULL) {
152
+ totalRows = jTotal->valueint;
153
+ } else {
154
+ // Reduce responses might skip total_rows
155
+ totalRows = rows.size();
156
+ }
152
157
  cJSON_Delete(cj);
153
158
  }
154
159
  if (resp->htresp) {
@@ -274,8 +279,8 @@ TEST_F(ViewsUnitTest, testReduce) {
274
279
  rc = lcb_view_query(instance, &vi, &vq);
275
280
  ASSERT_EQ(LCB_SUCCESS, rc);
276
281
  lcb_wait(instance);
277
- ASSERT_EQ(1411, vi.totalRows);
278
282
  ASSERT_EQ(1, vi.rows.size());
283
+ ASSERT_STREQ("1411", vi.rows[0].value.c_str());
279
284
 
280
285
  vi.clear();
281
286
  // Try with include_docs
@@ -401,5 +406,12 @@ TEST_F(ViewsUnitTest, testBackslashDocid)
401
406
  lcb_wait(instance);
402
407
  ASSERT_EQ(1, vi.rows.size());
403
408
  ASSERT_EQ(doc.size(), vi.rows[0].docContents.nvalue);
409
+
410
+ removeKey(instance, key);
411
+ vi.clear();
412
+ rc = lcb_view_query(instance, &vi, &cmd);
413
+ ASSERT_EQ(LCB_SUCCESS, rc);
414
+ lcb_wait(instance);
415
+ ASSERT_EQ(0, vi.rows.size());
404
416
  }
405
417
  }
@@ -19,6 +19,13 @@ TARGET_LINK_LIBRARIES(cbc-n1qlback couchbase)
19
19
  INSTALL(TARGETS cbc cbc-pillowfight cbc-n1qlback
20
20
  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
21
21
 
22
+ FIND_PACKAGE(OpenSSL)
23
+ IF(OPENSSL_FOUND AND (NOT LCB_NO_SSL))
24
+ INCLUDE_DIRECTORIES(${OPENSSL_INCLUDE_DIR})
25
+ ADD_DEFINITIONS(${OPENSSL_DEFINITIONS})
26
+ TARGET_LINK_LIBRARIES(cbc ${OPENSSL_LIBRARIES})
27
+ ENDIF()
28
+
22
29
  # Set this before INSTALL_PDBS in order to set the correct output name
23
30
  IF(MSVC)
24
31
  SET_TARGET_PROPERTIES(cbc PROPERTIES DEBUG_OUTPUT_NAME cbc_d)
@@ -38,9 +45,22 @@ IF(NOT WIN32)
38
45
  ADD_LIBRARY(linenoise OBJECT ${T_LINENOSE_SRC})
39
46
  SET_TARGET_PROPERTIES(linenoise PROPERTIES COMPILE_FLAGS "${LCB_CORE_CFLAGS}")
40
47
 
48
+ ADD_EXECUTABLE(cbc-subdoc cbc-subdoc.cc $<TARGET_OBJECTS:lcbtools> $<TARGET_OBJECTS:cliopts> $<TARGET_OBJECTS:linenoise>)
49
+ TARGET_LINK_LIBRARIES(cbc-subdoc couchbase)
50
+ INSTALL(TARGETS cbc-subdoc RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
51
+ SET_SOURCE_FILES_PROPERTIES(cbc-subdoc.cc PROPERTIES COMPILE_FLAGS "${LCB_CORE_CXXFLAGS}")
52
+
53
+ IF(HAVE_LIBEVENT2)
54
+ INCLUDE_DIRECTORIES(AFTER ${LIBEVENT_INCLUDE_DIR})
55
+ ADD_EXECUTABLE(cbc-proxy cbc-proxy.cc $<TARGET_OBJECTS:lcbtools> $<TARGET_OBJECTS:cliopts>)
56
+ TARGET_LINK_LIBRARIES(cbc-proxy couchbase ${LIBEVENT_LIBRARIES})
57
+ INSTALL(TARGETS cbc-proxy RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
58
+ SET_SOURCE_FILES_PROPERTIES(cbc-proxy.cc PROPERTIES COMPILE_FLAGS "${LCB_CORE_CXXFLAGS}")
59
+ ENDIF()
60
+
41
61
  LIST(APPEND CBC_SUBCOMMANDS
42
62
  cat create observe observe-seqno incr decr mcflush hash lock
43
- unlock rm stats version verbosity view n1ql admin
63
+ unlock rm stats version verbosity view n1ql admin ping
44
64
  bucket-create bucket-delete bucket-flush connstr write-config strerror
45
65
  touch role-list user-list user-upsert user-delete)
46
66