libcouchbase 1.0.4 → 1.1.0

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 (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