Skip to content

Commit

Permalink
MB-45066: Move WorkerConcurrencyTest to its own file
Browse files Browse the repository at this point in the history
And authenticate as Luke and select bucket

Change-Id: I57bbf15b53d882f583483b2f4d6ac6b1fdb23a13
Reviewed-on: http://review.couchbase.org/c/kv_engine/+/160777
Tested-by: Build Bot <build@couchbase.com>
Reviewed-by: Paolo Cocchi <paolo.cocchi@couchbase.com>
  • Loading branch information
trondn committed Sep 6, 2021
1 parent 2653aff commit 546a5e0
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 82 deletions.
1 change: 1 addition & 0 deletions tests/testapp/CMakeLists.txt
Expand Up @@ -67,6 +67,7 @@ set(memcached_testapp_SOURCES
testapp_subdoc.cc
testapp_subdoc_common.cc
testapp_subdoc_common.h
testapp_subdoc_concurrency.cc
testapp_subdoc_multipath.cc
testapp_subdoc_perf.cc
testapp_tenant.cc
Expand Down
82 changes: 0 additions & 82 deletions tests/testapp/testapp_subdoc.cc
Expand Up @@ -2124,85 +2124,3 @@ INSTANTIATE_TEST_SUITE_P(
::testing::Values(ClientJSONSupport::Yes,
ClientJSONSupport::No)),
McdTestappTest::PrintToStringCombinedName);

// Tests how a single worker handles multiple "concurrent" connections
// performing operations.
class WorkerConcurrencyTest : public TestappTest {
public:
static void SetUpTestCase() {
// Change the number of worker threads to one so we guarantee that
// multiple connections are handled by a single worker.
auto cfg = generate_config();
cfg["threads"] = 1;
doSetUpTestCaseWithConfiguration(cfg);
}
};

TEST_F(WorkerConcurrencyTest, SubdocArrayPushLast_Concurrent) {
// "Concurrently" add to two different array documents, using two
// connections. In this thread try to send data as fast as possible
// mixing on two sockets. Hopefully this is faster than the other
// end may consume the packets so that we'll end up with a "pipeline"
// of data on both connections.
auto& conn = getConnection();
conn.store("a", Vbid{0}, "[]");
conn.store("b", Vbid{0}, "[]");

auto c1 = conn.clone();
auto c2 = conn.clone();

const size_t push_count = 100;

std::vector<BinprotSubdocCommand> docA;
std::vector<BinprotSubdocCommand> docB;

// Build pipeline for the even commands.
std::string expected_a;
std::string expected_b;

for (unsigned int i = 0; i < push_count; i++) {
if ((i & 1) == 0) {
expected_a += std::to_string(i) + ",";
docA.emplace_back(BinprotSubdocCommand{
cb::mcbp::ClientOpcode::SubdocArrayPushLast,
"a",
"",
std::to_string(i)});
} else {
expected_b += std::to_string(i) + ",";
docB.emplace_back(BinprotSubdocCommand{
cb::mcbp::ClientOpcode::SubdocArrayPushLast,
"b",
"",
std::to_string(i)});
}
}

for (unsigned int i = 0; i < push_count / 2; i++) {
c1->sendCommand(docA[i]);
c2->sendCommand(docB[i]);
}

// Fixup the expected values - remove the trailing comma and bookend with
// [ ].
expected_a.insert(0, "[");
expected_a.replace(expected_a.size() - 1, 1, "]");
expected_b.insert(0, "[");
expected_b.replace(expected_b.size() - 1, 1, "]");

// Consume all the responses we should be expecting back.
for (unsigned int i = 0; i < push_count / 2; i++) {
BinprotResponse rsp;
c1->recvResponse(rsp);
ASSERT_TRUE(rsp.isSuccess());
c2->recvResponse(rsp);
ASSERT_TRUE(rsp.isSuccess());
}

// Validate correct data was written.
validate_json_document(conn, "a", expected_a);
validate_json_document(conn, "b", expected_b);

conn.remove("a", Vbid{0});
conn.remove("b", Vbid{0});
}
100 changes: 100 additions & 0 deletions tests/testapp/testapp_subdoc_concurrency.cc
@@ -0,0 +1,100 @@
/*
* Copyright 2015-Present Couchbase, Inc.
*
* Use of this software is governed by the Business Source License included
* in the file licenses/BSL-Couchbase.txt. As of the Change Date specified
* in that file, in accordance with the Business Source License, use of this
* software will be governed by the Apache License, Version 2.0, included in
* the file licenses/APL2.txt.
*/

#include "testapp_client_test.h"

/// Tests how a single worker handles multiple "concurrent" connections
/// performing operations.
class WorkerConcurrencyTest : public TestappTest {
public:
static void SetUpTestCase() {
// Change the number of worker threads to one so we guarantee that
// multiple connections are handled by a single worker.
auto cfg = generate_config();
cfg["threads"] = 1;
doSetUpTestCaseWithConfiguration(cfg);
}
};

/// "Concurrently" add to two different array documents, using two
/// connections. In this thread try to send data as fast as possible
/// mixing on two sockets. Hopefully this is faster than the other
/// end may consume the packets so that we'll end up with a "pipeline"
/// of data on both connections. (the default number of requests per
/// event cycle is 20 before we'll back off)
TEST_F(WorkerConcurrencyTest, SubdocArrayPushLast_Concurrent) {
rebuildUserConnection(false);

userConnection->store("a", Vbid{0}, "[]");
userConnection->store("b", Vbid{0}, "[]");

auto c1 = userConnection->clone();
c1->authenticate("Luke", mcd_env->getPassword("Luke"));
c1->selectBucket(bucketName);

auto c2 = userConnection->clone();
c2->authenticate("Luke", mcd_env->getPassword("Luke"));
c2->selectBucket(bucketName);

const size_t push_count = 200;

std::vector<BinprotSubdocCommand> docA;
std::vector<BinprotSubdocCommand> docB;

// Build pipeline for the even commands.
std::string expected_a;
std::string expected_b;

for (unsigned int i = 0; i < push_count; i++) {
if ((i & 1) == 0) {
expected_a += std::to_string(i) + ",";
docA.emplace_back(BinprotSubdocCommand{
cb::mcbp::ClientOpcode::SubdocArrayPushLast,
"a",
"",
std::to_string(i)});
} else {
expected_b += std::to_string(i) + ",";
docB.emplace_back(BinprotSubdocCommand{
cb::mcbp::ClientOpcode::SubdocArrayPushLast,
"b",
"",
std::to_string(i)});
}
}

for (unsigned int i = 0; i < push_count / 2; i++) {
c1->sendCommand(docA[i]);
c2->sendCommand(docB[i]);
}

// Fixup the expected values - remove the trailing comma and bookend with
// [ ].
expected_a.insert(0, "[");
expected_a.replace(expected_a.size() - 1, 1, "]");
expected_b.insert(0, "[");
expected_b.replace(expected_b.size() - 1, 1, "]");

// Consume all the responses we should be expecting back.
for (unsigned int i = 0; i < push_count / 2; i++) {
BinprotResponse rsp;
c1->recvResponse(rsp);
ASSERT_TRUE(rsp.isSuccess());
c2->recvResponse(rsp);
ASSERT_TRUE(rsp.isSuccess());
}

// Validate correct data was written.
validate_json_document(*userConnection, "a", expected_a);
validate_json_document(*userConnection, "b", expected_b);

userConnection->remove("a", Vbid{0});
userConnection->remove("b", Vbid{0});
}

0 comments on commit 546a5e0

Please sign in to comment.