couchbase 4.2.1 → 4.2.2

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 (162) hide show
  1. package/CMakeLists.txt +1 -0
  2. package/deps/couchbase-cxx-client/.gitmodules +3 -0
  3. package/deps/couchbase-cxx-client/.idea/misc.xml +1 -0
  4. package/deps/couchbase-cxx-client/.idea/vcs.xml +1 -0
  5. package/deps/couchbase-cxx-client/CMakeLists.txt +11 -1
  6. package/deps/couchbase-cxx-client/README.md +3 -3
  7. package/deps/couchbase-cxx-client/cmake/CompilerWarnings.cmake +4 -1
  8. package/deps/couchbase-cxx-client/cmake/VersionInfo.cmake +13 -1
  9. package/deps/couchbase-cxx-client/cmake/build_version.hxx.in +1 -0
  10. package/deps/couchbase-cxx-client/core/cluster.hxx +15 -5
  11. package/deps/couchbase-cxx-client/core/impl/build_deferred_query_indexes.cxx +17 -6
  12. package/deps/couchbase-cxx-client/core/impl/cluster.cxx +1 -1
  13. package/deps/couchbase-cxx-client/core/impl/collection_query_index_manager.cxx +93 -0
  14. package/deps/couchbase-cxx-client/core/impl/configuration_profiles_registry.cxx +11 -0
  15. package/deps/couchbase-cxx-client/core/impl/create_query_index.cxx +119 -0
  16. package/deps/couchbase-cxx-client/core/impl/drop_query_index.cxx +108 -0
  17. package/deps/couchbase-cxx-client/core/impl/get.cxx +1 -1
  18. package/deps/couchbase-cxx-client/core/impl/get_all_query_indexes.cxx +76 -0
  19. package/deps/couchbase-cxx-client/core/impl/query.cxx +5 -7
  20. package/deps/couchbase-cxx-client/core/impl/watch_query_indexes.cxx +168 -0
  21. package/deps/couchbase-cxx-client/core/io/mcbp_session.cxx +15 -1
  22. package/deps/couchbase-cxx-client/core/logger/configuration.hxx +3 -0
  23. package/deps/couchbase-cxx-client/core/logger/level.hxx +21 -0
  24. package/deps/couchbase-cxx-client/core/logger/logger.hxx +4 -6
  25. package/deps/couchbase-cxx-client/core/meta/CMakeLists.txt +4 -2
  26. package/deps/couchbase-cxx-client/core/meta/features.hxx +31 -0
  27. package/deps/couchbase-cxx-client/core/meta/version.cxx +67 -5
  28. package/deps/couchbase-cxx-client/core/meta/version.hxx +12 -1
  29. package/deps/couchbase-cxx-client/core/metrics/CMakeLists.txt +4 -1
  30. package/deps/couchbase-cxx-client/core/metrics/logging_meter.cxx +46 -5
  31. package/deps/couchbase-cxx-client/core/metrics/logging_meter.hxx +10 -26
  32. package/deps/couchbase-cxx-client/core/operations/document_get_projected.cxx +3 -2
  33. package/deps/couchbase-cxx-client/core/operations/document_query.cxx +10 -12
  34. package/deps/couchbase-cxx-client/core/operations/document_query.hxx +1 -3
  35. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.cxx +8 -14
  36. package/deps/couchbase-cxx-client/core/operations/management/query_index_build.hxx +2 -1
  37. package/deps/couchbase-cxx-client/core/operations/management/query_index_build_deferred.hxx +15 -8
  38. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.cxx +7 -14
  39. package/deps/couchbase-cxx-client/core/operations/management/query_index_create.hxx +2 -0
  40. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.cxx +11 -16
  41. package/deps/couchbase-cxx-client/core/operations/management/query_index_drop.hxx +2 -0
  42. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.cxx +8 -12
  43. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all.hxx +4 -3
  44. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.cxx +21 -12
  45. package/deps/couchbase-cxx-client/core/operations/management/query_index_get_all_deferred.hxx +3 -2
  46. package/deps/couchbase-cxx-client/core/origin.hxx +1 -1
  47. package/deps/couchbase-cxx-client/core/platform/uuid.cc +1 -2
  48. package/deps/couchbase-cxx-client/core/protocol/cmd_hello.hxx +5 -1
  49. package/deps/couchbase-cxx-client/core/query_context.hxx +79 -0
  50. package/deps/couchbase-cxx-client/core/tracing/CMakeLists.txt +3 -1
  51. package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.cxx +19 -4
  52. package/deps/couchbase-cxx-client/core/tracing/threshold_logging_tracer.hxx +2 -2
  53. package/deps/couchbase-cxx-client/core/transactions/async_attempt_context.hxx +10 -4
  54. package/deps/couchbase-cxx-client/core/transactions/atr_cleanup_entry.cxx +52 -63
  55. package/deps/couchbase-cxx-client/core/transactions/attempt_context.hxx +8 -3
  56. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.cxx +163 -126
  57. package/deps/couchbase-cxx-client/core/transactions/attempt_context_impl.hxx +24 -37
  58. package/deps/couchbase-cxx-client/core/transactions/forward_compat.hxx +4 -4
  59. package/deps/couchbase-cxx-client/core/transactions/internal/atr_cleanup_entry.hxx +51 -13
  60. package/deps/couchbase-cxx-client/core/transactions/internal/client_record.hxx +26 -1
  61. package/deps/couchbase-cxx-client/core/transactions/internal/doc_record.hxx +21 -0
  62. package/deps/couchbase-cxx-client/core/transactions/internal/logging.hxx +40 -18
  63. package/deps/couchbase-cxx-client/core/transactions/internal/transaction_context.hxx +5 -0
  64. package/deps/couchbase-cxx-client/core/transactions/result.hxx +26 -0
  65. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.cxx +48 -47
  66. package/deps/couchbase-cxx-client/core/transactions/staged_mutation.hxx +6 -6
  67. package/deps/couchbase-cxx-client/core/transactions/transaction_context.cxx +33 -19
  68. package/deps/couchbase-cxx-client/core/transactions/transaction_get_result.hxx +18 -2
  69. package/deps/couchbase-cxx-client/core/transactions/transaction_links.hxx +25 -2
  70. package/deps/couchbase-cxx-client/core/transactions/transactions.cxx +4 -4
  71. package/deps/couchbase-cxx-client/core/transactions/transactions_cleanup.cxx +49 -56
  72. package/deps/couchbase-cxx-client/core/transactions/waitable_op_list.hxx +7 -7
  73. package/deps/couchbase-cxx-client/core/transactions.hxx +0 -12
  74. package/deps/couchbase-cxx-client/core/utils/binary.hxx +1 -1
  75. package/deps/couchbase-cxx-client/core/utils/keyspace.hxx +55 -0
  76. package/deps/couchbase-cxx-client/couchbase/build_query_index_options.hxx +12 -45
  77. package/deps/couchbase-cxx-client/couchbase/cluster.hxx +1 -1
  78. package/deps/couchbase-cxx-client/couchbase/cluster_options.hxx +6 -7
  79. package/deps/couchbase-cxx-client/couchbase/collection.hxx +8 -0
  80. package/deps/couchbase-cxx-client/couchbase/collection_query_index_manager.hxx +218 -0
  81. package/deps/couchbase-cxx-client/couchbase/configuration_profiles_registry.hxx +3 -0
  82. package/deps/couchbase-cxx-client/couchbase/create_primary_query_index_options.hxx +166 -0
  83. package/deps/couchbase-cxx-client/couchbase/create_query_index_options.hxx +172 -0
  84. package/deps/couchbase-cxx-client/couchbase/drop_primary_query_index_options.hxx +129 -0
  85. package/deps/couchbase-cxx-client/couchbase/drop_query_index_options.hxx +116 -0
  86. package/deps/couchbase-cxx-client/couchbase/fmt/cas.hxx +1 -1
  87. package/deps/couchbase-cxx-client/couchbase/fmt/query_scan_consistency.hxx +46 -0
  88. package/deps/couchbase-cxx-client/couchbase/fmt/query_status.hxx +70 -0
  89. package/deps/couchbase-cxx-client/couchbase/fmt/tls_verify_mode.hxx +46 -0
  90. package/deps/couchbase-cxx-client/couchbase/get_all_query_indexes_options.hxx +100 -0
  91. package/deps/couchbase-cxx-client/{core → couchbase}/management/query_index.hxx +2 -2
  92. package/deps/couchbase-cxx-client/couchbase/metrics/meter.hxx +16 -0
  93. package/deps/couchbase-cxx-client/couchbase/query_index_manager.hxx +178 -6
  94. package/deps/couchbase-cxx-client/couchbase/query_options.hxx +1 -18
  95. package/deps/couchbase-cxx-client/couchbase/scope.hxx +5 -2
  96. package/deps/couchbase-cxx-client/couchbase/tracing/request_tracer.hxx +16 -0
  97. package/deps/couchbase-cxx-client/couchbase/transactions/async_attempt_context.hxx +11 -4
  98. package/deps/couchbase-cxx-client/couchbase/transactions/attempt_context.hxx +5 -3
  99. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_keyspace.hxx +16 -0
  100. package/deps/couchbase-cxx-client/couchbase/transactions/transaction_query_options.hxx +0 -6
  101. package/deps/couchbase-cxx-client/couchbase/watch_query_indexes_options.hxx +115 -0
  102. package/deps/couchbase-cxx-client/examples/minimal.cxx +3 -1
  103. package/deps/couchbase-cxx-client/test/test_integration_crud.cxx +72 -0
  104. package/deps/couchbase-cxx-client/test/test_integration_management.cxx +727 -310
  105. package/deps/couchbase-cxx-client/test/test_integration_query.cxx +4 -8
  106. package/deps/couchbase-cxx-client/test/test_integration_transcoders.cxx +14 -0
  107. package/deps/couchbase-cxx-client/test/test_transaction_transaction_public_blocking_api.cxx +34 -19
  108. package/deps/couchbase-cxx-client/test/test_unit_transaction_logging.cxx +66 -22
  109. package/deps/couchbase-cxx-client/test/test_unit_utils.cxx +51 -0
  110. package/deps/couchbase-cxx-client/test/tools/tool_kv_loader.cxx +2 -2
  111. package/deps/couchbase-cxx-client/test/utils/integration_test_guard.cxx +2 -0
  112. package/deps/couchbase-cxx-client/test/utils/wait_until.cxx +4 -4
  113. package/deps/couchbase-cxx-client/third_party/docopt/.travis.yml +103 -0
  114. package/deps/couchbase-cxx-client/third_party/docopt/CMakeLists.txt +129 -0
  115. package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-Boost-1.0 +23 -0
  116. package/deps/couchbase-cxx-client/third_party/docopt/LICENSE-MIT +23 -0
  117. package/deps/couchbase-cxx-client/third_party/docopt/README.rst +479 -0
  118. package/deps/couchbase-cxx-client/third_party/docopt/docopt-config.cmake +1 -0
  119. package/deps/couchbase-cxx-client/third_party/docopt/docopt.cpp +687 -0
  120. package/deps/couchbase-cxx-client/third_party/docopt/docopt.h +98 -0
  121. package/deps/couchbase-cxx-client/third_party/docopt/docopt.pc.in +9 -0
  122. package/deps/couchbase-cxx-client/third_party/docopt/docopt_private.h +676 -0
  123. package/deps/couchbase-cxx-client/third_party/docopt/docopt_util.h +122 -0
  124. package/deps/couchbase-cxx-client/third_party/docopt/docopt_value.h +341 -0
  125. package/deps/couchbase-cxx-client/third_party/docopt/examples/naval_fate.cpp +36 -0
  126. package/deps/couchbase-cxx-client/third_party/docopt/main.cpp +16 -0
  127. package/deps/couchbase-cxx-client/third_party/docopt/run_testcase.cpp +40 -0
  128. package/deps/couchbase-cxx-client/third_party/docopt/run_tests.py +72 -0
  129. package/deps/couchbase-cxx-client/third_party/docopt/testcases.docopt +957 -0
  130. package/deps/couchbase-cxx-client/tools/CMakeLists.txt +14 -0
  131. package/deps/couchbase-cxx-client/tools/cbc.cxx +65 -0
  132. package/deps/couchbase-cxx-client/tools/command.hxx +31 -0
  133. package/deps/couchbase-cxx-client/tools/command_registry.cxx +43 -0
  134. package/deps/couchbase-cxx-client/tools/command_registry.hxx +39 -0
  135. package/deps/couchbase-cxx-client/tools/get.cxx +267 -0
  136. package/deps/couchbase-cxx-client/tools/get.hxx +26 -0
  137. package/deps/couchbase-cxx-client/tools/query.cxx +441 -0
  138. package/deps/couchbase-cxx-client/tools/query.hxx +26 -0
  139. package/deps/couchbase-cxx-client/tools/utils.cxx +418 -0
  140. package/deps/couchbase-cxx-client/tools/utils.hxx +150 -0
  141. package/deps/couchbase-cxx-client/tools/version.cxx +82 -0
  142. package/deps/couchbase-cxx-client/tools/version.hxx +26 -0
  143. package/dist/authenticators.d.ts +2 -2
  144. package/dist/authenticators.js +1 -2
  145. package/dist/binding.d.ts +32 -16
  146. package/dist/cluster.js +14 -7
  147. package/dist/collection.d.ts +6 -0
  148. package/dist/collection.js +8 -0
  149. package/dist/queryexecutor.js +1 -1
  150. package/dist/queryindexmanager.d.ts +100 -4
  151. package/dist/queryindexmanager.js +344 -118
  152. package/dist/transactions.js +0 -2
  153. package/package.json +1 -1
  154. package/src/connection.cpp +2 -0
  155. package/src/connection.hpp +1 -0
  156. package/src/connection_autogen.cpp +16 -0
  157. package/src/jstocbpp_autogen.hpp +93 -23
  158. package/src/jstocbpp_basic.hpp +24 -0
  159. package/src/jstocbpp_transactions.hpp +0 -8
  160. package/tools/gen-bindings-js.js +1 -0
  161. package/tools/gen-bindings-json.py +4 -2
  162. package/deps/couchbase-cxx-client/core/transactions/logging.cxx +0 -107
@@ -127,8 +127,7 @@ TEST_CASE("integration: query on a collection", "[integration]")
127
127
  {
128
128
  couchbase::core::operations::query_request req{ fmt::format(
129
129
  R"(SELECT a, b FROM {} WHERE META().id = "{}")", collection_name, key) };
130
- req.bucket_name = integration.ctx.bucket;
131
- req.scope_name = scope_name;
130
+ req.query_context = fmt::format("default:`{}`.`{}`", integration.ctx.bucket, scope_name);
132
131
  req.mutation_state = { mutation_token };
133
132
  auto resp = test::utils::execute(integration.cluster, req);
134
133
  REQUIRE_SUCCESS(resp.ctx.ec);
@@ -140,8 +139,7 @@ TEST_CASE("integration: query on a collection", "[integration]")
140
139
  {
141
140
  couchbase::core::operations::query_request req{ fmt::format(
142
141
  R"(SELECT a, b FROM {} WHERE META().id = "{}")", collection_name, key) };
143
- req.bucket_name = integration.ctx.bucket;
144
- req.scope_name = "missing_scope";
142
+ req.query_context = fmt::format("default:`{}`.`{}`", integration.ctx.bucket, "missing_scope");
145
143
  req.mutation_state = { mutation_token };
146
144
  auto resp = test::utils::execute(integration.cluster, req);
147
145
  REQUIRE(resp.ctx.ec == couchbase::errc::query::index_failure);
@@ -150,8 +148,7 @@ TEST_CASE("integration: query on a collection", "[integration]")
150
148
  SECTION("missing collection")
151
149
  {
152
150
  couchbase::core::operations::query_request req{ fmt::format(R"(SELECT a, b FROM missing_collection WHERE META().id = "{}")", key) };
153
- req.bucket_name = integration.ctx.bucket;
154
- req.scope_name = scope_name;
151
+ req.query_context = fmt::format("default:`{}`.`{}`", integration.ctx.bucket, scope_name);
155
152
  req.mutation_state = { mutation_token };
156
153
  auto resp = test::utils::execute(integration.cluster, req);
157
154
  REQUIRE(resp.ctx.ec == couchbase::errc::query::index_failure);
@@ -161,8 +158,7 @@ TEST_CASE("integration: query on a collection", "[integration]")
161
158
  {
162
159
  couchbase::core::operations::query_request req{ fmt::format(
163
160
  R"(SELECT a, b FROM {} WHERE META().id = "{}")", collection_name, key) };
164
- req.bucket_name = integration.ctx.bucket;
165
- req.scope_name = scope_name;
161
+ req.query_context = fmt::format("default:`{}`.`{}`", integration.ctx.bucket, scope_name);
166
162
  req.mutation_state = { mutation_token };
167
163
  req.adhoc = false;
168
164
  auto resp = test::utils::execute(integration.cluster, req);
@@ -282,6 +282,7 @@ TEST_CASE("integration: get with projections and json transcoder", "[integration
282
282
  REQUIRE(resp.mutation_token().has_value());
283
283
  }
284
284
 
285
+ SECTION("all fields present")
285
286
  {
286
287
  auto [ctx, resp] = collection.get(id, couchbase::get_options{}.project({ "username", "full_name" })).get();
287
288
  REQUIRE_SUCCESS(ctx.ec());
@@ -293,6 +294,19 @@ TEST_CASE("integration: get with projections and json transcoder", "[integration
293
294
  REQUIRE(light_albert.birth_year != albert.birth_year);
294
295
  REQUIRE(light_albert.birth_year == 0);
295
296
  }
297
+
298
+ SECTION("with non-existent field in projections")
299
+ {
300
+ auto [ctx, resp] = collection.get(id, couchbase::get_options{}.project({ "username", "full_name", "non_existent_field" })).get();
301
+ REQUIRE_SUCCESS(ctx.ec());
302
+ REQUIRE_FALSE(resp.cas().empty());
303
+ auto light_albert = resp.content_as<profile>();
304
+ REQUIRE_FALSE(light_albert == albert);
305
+ REQUIRE(light_albert.username == albert.username);
306
+ REQUIRE(light_albert.full_name == albert.full_name);
307
+ REQUIRE(light_albert.birth_year != albert.birth_year);
308
+ REQUIRE(light_albert.birth_year == 0);
309
+ }
296
310
  }
297
311
 
298
312
  TEST_CASE("integration: get_and_touch and json transcoder", "[integration]")
@@ -33,13 +33,22 @@ txn_opts()
33
33
  opts.expiration_time(std::chrono::seconds(2));
34
34
  return opts;
35
35
  }
36
-
36
+ void
37
+ with_new_guard(std::function<void(test::utils::integration_test_guard&)> fn)
38
+ {
39
+ test::utils::integration_test_guard integration;
40
+ try {
41
+ fn(integration);
42
+ } catch (...) {
43
+ // noop
44
+ }
45
+ }
37
46
  void
38
47
  with_new_cluster(test::utils::integration_test_guard& integration, std::function<void(couchbase::cluster&)> fn)
39
48
  {
40
49
  // make new virginal public cluster
50
+
41
51
  asio::io_context io;
42
- auto guard = asio::make_work_guard(io);
43
52
  std::thread io_thread([&io]() { io.run(); });
44
53
  auto options = couchbase::cluster_options(integration.ctx.username, integration.ctx.password);
45
54
  auto [cluster, ec] = couchbase::cluster::connect(io, integration.ctx.connection_string, options).get();
@@ -52,8 +61,10 @@ with_new_cluster(test::utils::integration_test_guard& integration, std::function
52
61
  // noop, just eat it.
53
62
  }
54
63
  cluster.close();
55
- guard.reset();
56
- io_thread.join();
64
+ io.stop();
65
+ if (io_thread.joinable()) {
66
+ io_thread.join();
67
+ }
57
68
  }
58
69
 
59
70
  void
@@ -512,19 +523,20 @@ TEST_CASE("can query from a scope", "[transactions]")
512
523
 
513
524
  TEST_CASE("can get doc from bucket not yet opened", "[transactions]")
514
525
  {
515
- test::utils::integration_test_guard integration;
516
526
 
517
527
  auto id = test::utils::uniq_id("txn");
518
528
  {
529
+ test::utils::integration_test_guard integration;
519
530
  couchbase::cluster c(integration.cluster);
520
531
  auto coll = c.bucket(integration.ctx.bucket).default_collection();
521
532
  auto [err, upsert_res] = coll.upsert(id, content, {}).get();
522
533
  REQUIRE_SUCCESS(err.ec());
523
534
  }
524
535
 
525
- with_new_cluster(integration, [&](couchbase::cluster& cluster) {
526
- auto coll = cluster.bucket(integration.ctx.bucket).default_collection();
527
- auto result = cluster.transactions()->run(
536
+ with_new_guard([&](test::utils::integration_test_guard& integration) {
537
+ couchbase::cluster c(integration.cluster);
538
+ auto coll = c.bucket(integration.ctx.bucket).default_collection();
539
+ auto result = c.transactions()->run(
528
540
  [&id, &coll](couchbase::transactions::attempt_context& ctx) {
529
541
  auto doc = ctx.get(coll, id);
530
542
  CHECK_FALSE(doc->ctx().ec());
@@ -543,10 +555,11 @@ TEST_CASE("can insert doc into bucket not yet opened", "[transactions]")
543
555
 
544
556
  auto id = test::utils::uniq_id("txn");
545
557
 
546
- with_new_cluster(integration, [&](couchbase::cluster& cluster) {
547
- auto coll = cluster.bucket(integration.ctx.bucket).default_collection();
558
+ with_new_guard([&](test::utils::integration_test_guard& guard) {
559
+ couchbase::cluster c(guard.cluster);
560
+ auto coll = c.bucket(integration.ctx.bucket).default_collection();
548
561
 
549
- auto result = cluster.transactions()->run(
562
+ auto result = c.transactions()->run(
550
563
  [&id, &coll](couchbase::transactions::attempt_context& ctx) {
551
564
  auto doc = ctx.insert(coll, id, content);
552
565
  CHECK_FALSE(doc->ctx().ec());
@@ -564,21 +577,22 @@ TEST_CASE("can insert doc into bucket not yet opened", "[transactions]")
564
577
 
565
578
  TEST_CASE("can replace doc in bucket not yet opened", "[transactions]")
566
579
  {
567
- test::utils::integration_test_guard integration;
568
580
 
569
581
  auto id = test::utils::uniq_id("txn");
570
582
  {
583
+ test::utils::integration_test_guard integration;
571
584
  couchbase::cluster c(integration.cluster);
572
585
  auto coll = c.bucket(integration.ctx.bucket).default_collection();
573
586
  auto [err, upsert_res] = coll.upsert(id, content, {}).get();
574
587
  REQUIRE_SUCCESS(err.ec());
575
588
  }
576
589
 
577
- with_new_cluster(integration, [&](couchbase::cluster& cluster) {
578
- auto coll = cluster.bucket(integration.ctx.bucket).default_collection();
590
+ with_new_guard([&](test::utils::integration_test_guard& guard) {
591
+ couchbase::cluster c(guard.cluster);
592
+ auto coll = c.bucket(guard.ctx.bucket).default_collection();
579
593
  tao::json::value new_content = { { "some", "new content" } };
580
594
 
581
- auto result = cluster.transactions()->run(
595
+ auto result = c.transactions()->run(
582
596
  [&id, &coll, new_content](couchbase::transactions::attempt_context& ctx) {
583
597
  auto get_doc = ctx.get(coll, id);
584
598
  CHECK_FALSE(get_doc->ctx().ec());
@@ -598,20 +612,21 @@ TEST_CASE("can replace doc in bucket not yet opened", "[transactions]")
598
612
 
599
613
  TEST_CASE("can remove doc in bucket not yet opened", "[transactions]")
600
614
  {
601
- test::utils::integration_test_guard integration;
602
615
 
603
616
  auto id = test::utils::uniq_id("txn");
604
617
  {
618
+ test::utils::integration_test_guard integration;
605
619
  couchbase::cluster c(integration.cluster);
606
620
  auto coll = c.bucket(integration.ctx.bucket).default_collection();
607
621
  auto [err, upsert_res] = coll.upsert(id, content, {}).get();
608
622
  REQUIRE_SUCCESS(err.ec());
609
623
  }
610
624
 
611
- with_new_cluster(integration, [&](couchbase::cluster& cluster) {
612
- auto coll = cluster.bucket(integration.ctx.bucket).default_collection();
625
+ with_new_guard([&](test::utils::integration_test_guard& guard) {
626
+ couchbase::cluster c(guard.cluster);
627
+ auto coll = c.bucket(guard.ctx.bucket).default_collection();
613
628
  tao::json::value new_content = { { "some", "new content" } };
614
- auto result = cluster.transactions()->run(
629
+ auto result = c.transactions()->run(
615
630
  [&id, &coll, new_content](couchbase::transactions::attempt_context& ctx) {
616
631
  auto get_doc = ctx.get(coll, id);
617
632
  CHECK_FALSE(get_doc->ctx().ec());
@@ -14,9 +14,11 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- #include "core/transactions/internal/logging.hxx"
17
+ #include "test/utils/wait_until.hxx"
18
18
  #include "test_helper.hxx"
19
- #include <core/transactions.hxx>
19
+ #include <core/logger/configuration.hxx>
20
+ #include <core/logger/logger.hxx>
21
+ #include <core/transactions/internal/logging.hxx>
20
22
 
21
23
  #include <spdlog/sinks/base_sink.h>
22
24
 
@@ -28,8 +30,10 @@ using namespace couchbase::core::transactions;
28
30
  class TrivialFileSink : public spdlog::sinks::base_sink<std::mutex>
29
31
  {
30
32
  public:
31
- std::string output() const
33
+ std::string output()
32
34
  {
35
+ // prevent data race if sink_it_ is called
36
+ std::lock_guard<std::mutex> lock(mut_);
33
37
  return out_.str();
34
38
  }
35
39
 
@@ -38,6 +42,8 @@ class TrivialFileSink : public spdlog::sinks::base_sink<std::mutex>
38
42
  {
39
43
  spdlog::memory_buf_t formatted;
40
44
  base_sink<std::mutex>::formatter_->format(msg, formatted);
45
+ // prevent data race when calling output()
46
+ std::lock_guard<std::mutex> lock(mut_);
41
47
  out_ << formatted.data();
42
48
  }
43
49
  void flush_() override
@@ -46,41 +52,79 @@ class TrivialFileSink : public spdlog::sinks::base_sink<std::mutex>
46
52
 
47
53
  private:
48
54
  std::stringstream out_;
55
+ // needed since we examine the internal state of this object
56
+ std::mutex mut_;
49
57
  };
50
58
 
59
+ bool
60
+ sink_has_output(std::shared_ptr<TrivialFileSink> sink)
61
+ {
62
+ return test::utils::wait_until([&]() { return !sink->output().empty(); }, std::chrono::seconds(2), std::chrono::milliseconds(100));
63
+ }
64
+
65
+ bool
66
+ sink_is_empty(std::shared_ptr<TrivialFileSink> sink)
67
+ {
68
+ // now, we need to be sure it is empty, and stays that way for some period of time,
69
+ // since async loggers don't flush immediately. The logger is set to flush every
70
+ // second, so waiting 2 or 3 seems reasonable
71
+ if (sink->output().empty()) {
72
+ std::this_thread::sleep_for(std::chrono::seconds(2));
73
+ return sink->output().empty();
74
+ }
75
+ return false;
76
+ }
77
+
78
+ bool
79
+ sink_output_contains(std::shared_ptr<TrivialFileSink> sink, const std::string& msg)
80
+ {
81
+ return std::string::npos != sink->output().find(msg);
82
+ }
83
+
84
+ void
85
+ create_logger(std::shared_ptr<TrivialFileSink> sink, couchbase::core::logger::level level)
86
+ {
87
+ couchbase::core::logger::configuration conf{};
88
+ conf.log_level = level;
89
+ conf.sink = sink;
90
+ conf.console = false;
91
+ couchbase::core::logger::create_file_logger(conf);
92
+ }
93
+
51
94
  TEST_CASE("transactions: can use custom sink", "[unit]")
52
95
  {
53
- couchbase::core::logger::create_blackhole_logger();
54
96
  std::string log_message = "I am a log";
55
97
  auto sink = std::make_shared<TrivialFileSink>();
56
- create_loggers(couchbase::core::logger::level::debug, sink);
57
- txn_log->debug(log_message);
58
- txn_log->flush();
59
- REQUIRE_FALSE(sink->output().empty());
60
- REQUIRE(std::string::npos != sink->output().find(log_message));
98
+ create_logger(sink, couchbase::core::logger::level::trace);
99
+ CB_TXN_LOG_DEBUG(log_message);
100
+ couchbase::core::logger::flush();
101
+ // ASYNC logger, so flush returns immediately. Gotta wait...
102
+ REQUIRE(sink_has_output(sink));
103
+ REQUIRE(sink_output_contains(sink, log_message));
61
104
  }
62
105
 
63
106
  TEST_CASE("transactions: custom sink respects log levels", "[unit]")
64
107
  {
65
- couchbase::core::logger::create_blackhole_logger();
66
108
  std::string log_message = "I am a log";
109
+ std::string log_message2 = "I am also a log";
67
110
  auto sink = std::make_shared<TrivialFileSink>();
68
- create_loggers(couchbase::core::logger::level::info, sink);
69
- txn_log->debug(log_message);
70
- txn_log->flush();
71
- REQUIRE(sink->output().empty());
72
- couchbase::core::logger::create_console_logger();
111
+ create_logger(sink, couchbase::core::logger::level::info);
112
+ CB_TXN_LOG_DEBUG(log_message);
113
+ couchbase::core::logger::flush();
114
+ REQUIRE(sink_is_empty(sink));
115
+ CB_TXN_LOG_INFO(log_message2);
116
+ couchbase::core::logger::flush();
117
+ REQUIRE(sink_has_output(sink));
118
+ REQUIRE(sink_output_contains(sink, log_message2));
73
119
  }
74
120
 
75
121
  TEST_CASE("transactions: custom sink respects log level changes", "[unit]")
76
122
  {
77
- couchbase::core::logger::create_blackhole_logger();
78
123
  std::string log_message = "I am a log";
79
124
  auto sink = std::make_shared<TrivialFileSink>();
80
- create_loggers(couchbase::core::logger::level::debug, sink);
81
- set_transactions_log_level(couchbase::core::logger::level::info);
82
- txn_log->debug(log_message);
83
- txn_log->flush();
84
- REQUIRE(sink->output().empty());
85
- couchbase::core::logger::create_console_logger();
125
+ create_logger(sink, couchbase::core::logger::level::trace);
126
+ couchbase::core::logger::set_log_levels(couchbase::core::logger::level::info);
127
+ CB_TXN_LOG_DEBUG(log_message);
128
+ couchbase::core::logger::flush();
129
+ REQUIRE(sink_is_empty(sink));
86
130
  }
@@ -211,3 +211,54 @@ TEST_CASE("unit: base64", "[unit]")
211
211
  REQUIRE(couchbase::core::base64::encode(binary, false) == base64);
212
212
  REQUIRE(couchbase::core::base64::encode(binary, true) == base64_pretty);
213
213
  }
214
+
215
+ namespace couchbase::core::meta
216
+ {
217
+ std::string
218
+ parse_git_describe_output(const std::string& git_describe_output);
219
+ }
220
+
221
+ TEST_CASE("unit: semantic version string", "[unit]")
222
+ {
223
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("1.0.0-beta.4-16-gfbc9922") == "1.0.0-beta.4+16.fbc9922");
224
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("1.0.0-16-gfbc9922") == "1.0.0+16.fbc9922");
225
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("") == "");
226
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("unknown") == "");
227
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("invalid") == "");
228
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("1.0.0.0.0") == "");
229
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("1.0.0-beta.4-0-gfbc9922") == "1.0.0-beta.4");
230
+ REQUIRE(couchbase::core::meta::parse_git_describe_output("1.0.0-beta.4") == "1.0.0-beta.4");
231
+ }
232
+
233
+ #if 0
234
+ // This test is commented out because, it is not necessary to run it with the suite, but it still useful for debugging.
235
+
236
+ #include "core/platform/uuid.h"
237
+
238
+ TEST_CASE("unit: uuid collision", "[unit]")
239
+ {
240
+ std::array<std::set<std::string>, 10> uuids{};
241
+ std::vector<std::thread> threads{};
242
+ threads.reserve(10);
243
+
244
+ for (std::size_t t = 0; t < 10; ++t) {
245
+ threads.emplace_back([&uuids, t]() {
246
+ for (std::size_t i = 0; i < 1'000'000; ++i) {
247
+ auto uuid = couchbase::core::uuid::to_string(couchbase::core::uuid::random());
248
+ uuids[t].insert(uuid);
249
+ }
250
+ });
251
+ }
252
+ for (std::size_t t = 0; t < 10; ++t) {
253
+ threads[t].join();
254
+ REQUIRE(uuids[t].size() == 1'000'000);
255
+ }
256
+
257
+ std::set<std::string> all_uuids{};
258
+ for (std::size_t t = 0; t < 10; ++t) {
259
+ for (const auto& uuid : uuids[t]) {
260
+ REQUIRE(all_uuids.insert(uuid).second);
261
+ }
262
+ }
263
+ }
264
+ #endif
@@ -106,7 +106,7 @@ static std::string
106
106
  random_text(std::size_t length)
107
107
  {
108
108
  std::string alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
109
- static thread_local std::minstd_rand gen{ std::random_device()() };
109
+ static thread_local std::mt19937_64 gen{ std::random_device()() };
110
110
  std::uniform_int_distribution<std::size_t> dis(0, alphabet.size() - 1);
111
111
  std::string text(length, '-');
112
112
  for (std::size_t i = 0; i < length; ++i) {
@@ -230,7 +230,7 @@ main()
230
230
  hit_chance_for_get = std::stod(val, nullptr);
231
231
  }
232
232
 
233
- static thread_local std::minstd_rand gen{ std::random_device()() };
233
+ static thread_local std::mt19937_64 gen{ std::random_device()() };
234
234
  std::uniform_real_distribution<double> dist(0, 1);
235
235
 
236
236
  std::atomic_uint64_t total{};
@@ -90,6 +90,7 @@ integration_test_guard::integration_test_guard(const couchbase::core::cluster_op
90
90
  // for now, lets _only_ add a tracer or meter from the incoming options
91
91
  connstr.options.meter = opts.meter;
92
92
  connstr.options.tracer = opts.tracer;
93
+ connstr.options.enable_mutation_tokens = opts.enable_mutation_tokens;
93
94
  couchbase::core::origin orig(auth, connstr);
94
95
  io_threads = spawn_io_threads(io, ctx.number_of_io_threads);
95
96
  open_cluster(cluster, orig);
@@ -98,6 +99,7 @@ integration_test_guard::integration_test_guard(const couchbase::core::cluster_op
98
99
  integration_test_guard::~integration_test_guard()
99
100
  {
100
101
  close_cluster(cluster);
102
+ io.stop();
101
103
  for (auto& thread : io_threads) {
102
104
  thread.join();
103
105
  }
@@ -80,11 +80,11 @@ wait_until_cluster_connected(const std::string& username, const std::string& pas
80
80
  asio::io_context io;
81
81
  auto guard = asio::make_work_guard(io);
82
82
  std::thread io_thread([&io]() { io.run(); });
83
- auto resp = couchbase::cluster::connect(io, connection_string, cluster_options).get();
84
- resp.first.close();
83
+ auto [cluster, ec] = couchbase::cluster::connect(io, connection_string, cluster_options).get();
84
+ cluster.close();
85
85
  guard.reset();
86
86
  io_thread.join();
87
- return resp.second.value() == 0;
87
+ return ec.value() == 0;
88
88
  });
89
89
  if (connected) {
90
90
  std::this_thread::sleep_for(std::chrono::seconds(1));
@@ -92,4 +92,4 @@ wait_until_cluster_connected(const std::string& username, const std::string& pas
92
92
 
93
93
  return connected;
94
94
  }
95
- } // namespace test::utils
95
+ } // namespace test::utils
@@ -0,0 +1,103 @@
1
+ language: cpp
2
+ sudo: false # Use the new container infrastructure
3
+
4
+ matrix:
5
+ include:
6
+ - os: linux
7
+ env:
8
+ - COMPILER=g++-7
9
+ addons:
10
+ apt:
11
+ sources: ['ubuntu-toolchain-r-test']
12
+ packages: ["g++-7", "cmake-data", "cmake"]
13
+ - os: linux
14
+ env:
15
+ - COMPILER=g++-8
16
+ addons:
17
+ apt:
18
+ sources: ['ubuntu-toolchain-r-test']
19
+ packages: ["g++-8", "cmake-data", "cmake"]
20
+ - os: linux
21
+ env:
22
+ - COMPILER=g++-9
23
+ addons:
24
+ apt:
25
+ sources: ['ubuntu-toolchain-r-test']
26
+ packages: ["g++-9", "cmake-data", "cmake"]
27
+ - os: linux
28
+ env:
29
+ - COMPILER=g++-9 USE_BOOST_REGEX=ON
30
+ addons:
31
+ apt:
32
+ sources: ['ubuntu-toolchain-r-test']
33
+ packages: ["g++-9", "cmake-data", "cmake", "libboost-regex-dev"]
34
+
35
+ - os: linux
36
+ env:
37
+ - COMPILER=clang++-3.6 STDLIB=libc++
38
+ addons:
39
+ apt:
40
+ sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.6', 'george-edison55-precise-backports']
41
+ packages: ["clang-3.6", "cmake-data", "cmake"]
42
+
43
+ - os: linux
44
+ env:
45
+ - COMPILER=clang++-8 STDLIB=libc++
46
+ addons:
47
+ apt:
48
+ sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-8']
49
+ packages: ["clang-8", "cmake-data", "cmake"]
50
+
51
+ - os: osx
52
+ osx_image: xcode9.4
53
+ env:
54
+ - COMPILER=clang++ V='Apple LLVM 9.1'
55
+ - COMPILER=clang++ V='Apple LLVM 9.1' WITH_CPP14=true
56
+
57
+ - os: osx
58
+ osx_image: xcode10.3
59
+ env:
60
+ - COMPILER=clang++ V='Apple LLVM 10.0'
61
+ - COMPILER=clang++ V='Apple LLVM 10.0' WITH_CPP14=true
62
+ - os: osx
63
+ osx_image: xcode11.2
64
+ env:
65
+ - COMPILER=clang++ V='Apple LLVM 11.0'
66
+ - COMPILER=clang++ V='Apple LLVM 11.0' WITH_CPP14=true
67
+ - os: osx
68
+ osx_image: xcode11.2
69
+ env:
70
+ - COMPILER=clang++ V='Apple LLVM 11.0'
71
+ - COMPILER=clang++ V='Apple LLVM 11.0' WITH_CPP17=true
72
+
73
+ before_install:
74
+ - CMAKE_CXX_FLAGS+=" -Wall"
75
+ - |
76
+ if [[ "${WITH_CPP14}" == "true" ]]; then
77
+ CMAKE_OPTIONS+=" -DCMAKE_CXX_STANDARD=14"
78
+ fi
79
+ - |
80
+ if [[ "${WITH_CPP17}" == "true" ]]; then
81
+ CMAKE_OPTIONS+=" -DCMAKE_CXX_STANDARD=17"
82
+ fi
83
+ - |
84
+ if [[ "${USE_BOOST_REGEX}" == "ON" ]]; then
85
+ CMAKE_OPTIONS+=" -DUSE_BOOST_REGEX=ON"
86
+ CMAKE_OPTIONS+=" -DBoost_REGEX_LIBRARY_DEBUG=/usr/lib/x86_64-linux-gnu/libboost_regex.so"
87
+ CMAKE_OPTIONS+=" -DBoost_REGEX_LIBRARY_RELEASE=/usr/lib/x86_64-linux-gnu/libboost_regex.so"
88
+ fi
89
+ - |
90
+ if [[ "${STDLIB}" == "libc++" ]]; then
91
+ CMAKE_CXX_FLAGS+=" -stdlib=libc++"
92
+ fi
93
+ - ${COMPILER} --version
94
+
95
+ before_script:
96
+ - rm -rf build/
97
+ - mkdir build
98
+ - cd build
99
+ - cmake -DCMAKE_CXX_COMPILER=${COMPILER} -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DWITH_TESTS=1 -DWITH_EXAMPLE=1 ${CMAKE_OPTIONS} ..
100
+
101
+ script:
102
+ - cmake --build .
103
+ - python run_tests
@@ -0,0 +1,129 @@
1
+ cmake_minimum_required(VERSION 3.1)
2
+ project(docopt.cpp VERSION 0.6.2)
3
+
4
+ include(GNUInstallDirs)
5
+
6
+ #============================================================================
7
+ # Settable options
8
+ #============================================================================
9
+ option(WITH_TESTS "Build tests." OFF)
10
+ option(WITH_EXAMPLE "Build example." OFF)
11
+ option(USE_BOOST_REGEX "Replace std::regex with Boost.Regex" OFF)
12
+
13
+ #============================================================================
14
+ # Internal compiler options
15
+ #============================================================================
16
+ # C++ standard
17
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
18
+ set(CMAKE_CXX_EXTENSIONS OFF)
19
+ if(NOT CMAKE_CXX_STANDARD OR CMAKE_CXX_STANDARD LESS 11)
20
+ set(CMAKE_CXX_STANDARD 11)
21
+ endif()
22
+
23
+ #============================================================================
24
+ # Sources & headers
25
+ #============================================================================
26
+ set(docopt_SOURCES docopt.cpp)
27
+ set(docopt_HEADERS
28
+ docopt.h
29
+ docopt_private.h
30
+ docopt_util.h
31
+ docopt_value.h
32
+ )
33
+
34
+ #============================================================================
35
+ # Compile targets
36
+ #============================================================================
37
+ add_library(docopt ${docopt_SOURCES} ${docopt_HEADERS})
38
+ set_target_properties(docopt PROPERTIES
39
+ VERSION ${PROJECT_VERSION}
40
+ SOVERSION ${PROJECT_VERSION_MAJOR}
41
+ )
42
+
43
+ target_include_directories(docopt PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}> $<INSTALL_INTERFACE:include/docopt>)
44
+
45
+ if(MSVC AND BUILD_SHARED_LIBS)
46
+ # DOCOPT_DLL: Must be specified when building *and* when using the DLL.
47
+ # That's what the "PUBLIC" means.
48
+ # DOCOPT_EXPORTS: Must use __declspec(dllexport) when building the DLL.
49
+ # "PRIVATE" means it's only defined when building the DLL.
50
+ target_compile_definitions(docopt PUBLIC DOCOPT_DLL
51
+ PRIVATE DOCOPT_EXPORTS)
52
+ endif()
53
+
54
+ if(USE_BOOST_REGEX)
55
+ add_definitions("-DDOCTOPT_USE_BOOST_REGEX")
56
+ # This is needed on Linux, where linking a static library into docopt.so
57
+ # fails because boost static libs are not compiled with -fPIC
58
+ set(Boost_USE_STATIC_LIBS OFF)
59
+ find_package(Boost 1.53 REQUIRED COMPONENTS regex)
60
+ include_directories(${Boost_INCLUDE_DIRS})
61
+ target_link_libraries(docopt ${Boost_LIBRARIES})
62
+ endif()
63
+
64
+ #============================================================================
65
+ # Examples
66
+ #============================================================================
67
+ if(WITH_EXAMPLE)
68
+ add_executable(docopt_example examples/naval_fate.cpp)
69
+ target_link_libraries(docopt_example docopt)
70
+ endif()
71
+
72
+ #============================================================================
73
+ # Tests
74
+ #============================================================================
75
+ if(WITH_TESTS)
76
+ set(TESTPROG "${CMAKE_CURRENT_BINARY_DIR}/run_testcase")
77
+ set(TESTCASES "${PROJECT_SOURCE_DIR}/testcases.docopt")
78
+ add_executable(run_testcase run_testcase.cpp)
79
+ target_link_libraries(run_testcase docopt)
80
+ configure_file(
81
+ "${PROJECT_SOURCE_DIR}/run_tests.py"
82
+ "${CMAKE_CURRENT_BINARY_DIR}/run_tests"
83
+ ESCAPE_QUOTES
84
+ )
85
+ add_test("Testcases docopt" ${TESTPROG})
86
+ endif()
87
+
88
+ #============================================================================
89
+ # Install
90
+ #============================================================================
91
+ set(export_name "docopt-targets")
92
+
93
+ # Runtime package
94
+ install(TARGETS docopt EXPORT ${export_name}
95
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
96
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
97
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
98
+
99
+ # Development package
100
+ install(FILES ${docopt_HEADERS} DESTINATION include/docopt)
101
+
102
+ # CMake Package
103
+ include(CMakePackageConfigHelpers)
104
+ write_basic_package_version_file("${PROJECT_BINARY_DIR}/docopt-config-version.cmake" COMPATIBILITY SameMajorVersion)
105
+ install(FILES docopt-config.cmake ${PROJECT_BINARY_DIR}/docopt-config-version.cmake DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")
106
+ install(EXPORT ${export_name} DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/docopt")
107
+
108
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/docopt.pc.in ${CMAKE_CURRENT_BINARY_DIR}/docopt.pc @ONLY)
109
+ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/docopt.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
110
+
111
+ #============================================================================
112
+ # CPack
113
+ #============================================================================
114
+ set(CPACK_PACKAGE_NAME "docopt")
115
+ set(CPACK_DEBIAN_PACKAGE_DEPENDS "")
116
+ set(CPACK_RPM_PACKAGE_REQUIRES "")
117
+ set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Beautiful command line interfaces")
118
+ set(CPACK_PACKAGE_VENDOR "Jared Grubb")
119
+ set(CPACK_PACKAGE_CONTACT ${CPACK_PACKAGE_VENDOR})
120
+ set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.rst")
121
+ set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE-MIT")
122
+ set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
123
+ set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
124
+ set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
125
+ set(CPACK_DEBIAN_PACKAGE_SECTION "Development")
126
+ set(CPACK_RPM_PACKAGE_GROUP "Development/Libraries")
127
+ set(CPACK_RPM_PACKAGE_LICENSE "MIT")
128
+ set(CPACK_STRIP_FILES TRUE)
129
+ include(CPack)