couchbase 4.2.1 → 4.2.2

Sign up to get free protection for your applications and to get access to all the features.
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)