Skip to content

Commit

Permalink
Updated the response from query and listDocuments.
Browse files Browse the repository at this point in the history
  • Loading branch information
abdulkareem-siddiq committed Sep 2, 2021
1 parent c3e82ba commit efc4e49
Show file tree
Hide file tree
Showing 12 changed files with 271 additions and 188 deletions.
1 change: 1 addition & 0 deletions CosmosClient.sln
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{8350FE6A-E
docs\header.html = docs\header.html
docs\mainpage.md = docs\mainpage.md
docs\rebuild-docs.ps1 = docs\rebuild-docs.ps1
docs\work-in-progress.png = docs\work-in-progress.png
EndProjectSection
EndProject
Global
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ CosmosClient : Azure Cosmos REST-API Client for Modern C++
![](https://img.shields.io/azure-devops/coverage/siddiqsoft/siddiqsoft/15)
<!-- end badges -->

<img src="docs/work-in-progress.jpeg" width="10%" align="right" />
![](docs/work-in-progress.png)


# Motivation

Expand Down
2 changes: 1 addition & 1 deletion docs/Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ PROJECT_LOGO = ../nuget/Siddiq-Software-Avatar.png
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.

OUTPUT_DIRECTORY =
OUTPUT_DIRECTORY = .

# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
Expand Down
2 changes: 1 addition & 1 deletion docs/html
Submodule html updated 95 files
+22 −22 _cosmos_client_8cpp.html
+2 −2 _cosmos_client_8cpp.js
+538 −505 _cosmos_client_8cpp_source.html
+4 −4 _cosmos_connection_8cpp.html
+94 −96 _cosmos_connection_8cpp_source.html
+1 −1 _cosmos_endpoint_8cpp.html
+9 −9 _cosmos_endpoint_8cpp_source.html
+4 −2 annotated.html
+3 −1 annotated_dup.js
+9 −9 azure-cosmos-restcl_8hpp.html
+2 −1 azure-cosmos-restcl_8hpp.js
+690 −663 azure-cosmos-restcl_8hpp_source.html
+2 −2 classes.html
+4 −4 classsiddiqsoft_1_1_cosmos_client-members.html
+102 −80 classsiddiqsoft_1_1_cosmos_client.html
+3 −3 classsiddiqsoft_1_1_cosmos_client.js
+1 −1 dir_59425e443f801f1f2fd8bbe4959a3ccf.html
+1 −1 dir_68267d1309a1af8e8297ef4c3efbcdba.html
+1 −1 files.html
+13 −8 functions.html
+104 −0 functions_enum.html
+12 −6 functions_func.html
+1 −1 functions_rela.html
+5 −3 functions_vars.html
+1 −1 globals.html
+1 −1 globals_defs.html
+1 −1 globals_func.html
+8 −6 hierarchy.html
+3 −0 hierarchy.js
+11 −10 index.html
+1 −1 mainpage_8md.html
+3 −2 menudata.js
+1 −2 namespacemembers.html
+1 −1 namespacemembers_func.html
+2 −1 namespacemembers_type.html
+4 −2 namespaces.html
+15 −32 namespacesiddiqsoft.html
+2 −1 namespacesiddiqsoft.js
+2 −2 navtreedata.js
+85 −67 navtreeindex0.js
+20 −17 search/all_2.js
+2 −1 search/all_3.js
+1 −1 search/all_7.js
+2 −1 search/all_9.js
+1 −1 search/all_a.js
+2 −1 search/all_b.js
+1 −1 search/all_c.js
+1 −1 search/all_d.js
+5 −3 search/all_e.js
+1 −1 search/all_f.js
+3 −1 search/classes_0.js
+37 −0 search/enums_0.html
+4 −0 search/enums_0.js
+37 −0 search/enumvalues_0.html
+4 −0 search/enumvalues_0.js
+37 −0 search/enumvalues_1.html
+4 −0 search/enumvalues_1.js
+1 −1 search/functions_0.js
+1 −1 search/functions_3.js
+2 −4 search/functions_4.js
+4 −1 search/functions_5.js
+1 −4 search/functions_6.js
+4 −1 search/functions_7.js
+1 −2 search/functions_8.js
+2 −2 search/functions_9.js
+37 −0 search/functions_a.html
+5 −0 search/functions_a.js
+16 −13 search/searchdata.js
+2 −1 search/typedefs_0.js
+5 −4 search/variables_1.js
+1 −1 search/variables_2.js
+1 −1 search/variables_3.js
+1 −2 search/variables_4.js
+2 −1 search/variables_5.js
+2 −1 search/variables_8.js
+5 −3 structsiddiqsoft_1_1_cosmos_connection-members.html
+97 −23 structsiddiqsoft_1_1_cosmos_connection.html
+7 −2 structsiddiqsoft_1_1_cosmos_connection.js
+9 −10 structsiddiqsoft_1_1_cosmos_endpoint-members.html
+20 −41 structsiddiqsoft_1_1_cosmos_endpoint.html
+1 −2 structsiddiqsoft_1_1_cosmos_endpoint.js
+112 −0 structsiddiqsoft_1_1_cosmos_iterable_response_type-members.html
+244 −0 structsiddiqsoft_1_1_cosmos_iterable_response_type.html
+5 −0 structsiddiqsoft_1_1_cosmos_iterable_response_type.js
+ structsiddiqsoft_1_1_cosmos_iterable_response_type.png
+110 −0 structsiddiqsoft_1_1_cosmos_response_type-members.html
+226 −0 structsiddiqsoft_1_1_cosmos_response_type.html
+6 −0 structsiddiqsoft_1_1_cosmos_response_type.js
+ structsiddiqsoft_1_1_cosmos_response_type.png
+1 −1 structstd_1_1formatter_3_01siddiqsoft_1_1_cosmos_client_01_4-members.html
+3 −3 structstd_1_1formatter_3_01siddiqsoft_1_1_cosmos_client_01_4.html
+1 −1 structstd_1_1formatter_3_01siddiqsoft_1_1_cosmos_connection_01_4-members.html
+3 −3 structstd_1_1formatter_3_01siddiqsoft_1_1_cosmos_connection_01_4.html
+1 −1 structstd_1_1formatter_3_01siddiqsoft_1_1_cosmos_endpoint_01_4-members.html
+3 −3 structstd_1_1formatter_3_01siddiqsoft_1_1_cosmos_endpoint_01_4.html
2 changes: 1 addition & 1 deletion docs/mainpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

@tableofcontents

<img src="work-in-progress.jpeg" width="10%" align="right" />
<img src="work-in-progress.png" width="10%" align="right" />

# Features
- C++20 Azure Cosmos REST API client.
Expand Down
Binary file added docs/work-in-progress.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
235 changes: 145 additions & 90 deletions src/azure-cosmos-restcl.hpp

Large diffs are not rendered by default.

184 changes: 105 additions & 79 deletions tests/CosmosClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ TEST(CosmosClient, example1)
// ...useful with cDoc..

// Remove the just created document..
auto [rc4, delDoc] = cc.remove(dbName, collectionName, cDoc.value("id", docId), pkId);
auto rc4 = cc.remove(dbName, collectionName, cDoc.value("id", docId), pkId);
EXPECT_EQ(204, rc4);
}
}
Expand Down Expand Up @@ -179,7 +179,7 @@ TEST(CosmosClient, discoverRegions)

// The configure calls the method discoverRegions
cc.configure({{"partitionKeyNames", {"__pk"}}, {"connectionStrings", {priConnStr, secConnStr}}});

nlohmann::json info = cc;
EXPECT_TRUE(info.contains("serviceSettings"));
EXPECT_TRUE(info.contains("database"));
Expand Down Expand Up @@ -212,24 +212,23 @@ TEST(CosmosClient, discoverRegions_BadPrimary)

cc.configure({{"partitionKeyNames", {"__pk"}}, {"connectionStrings", {priConnStr, secConnStr}}});

std::cerr << "Configuration: " << cc.configuration().dump(2) << std::endl;

// First attempt should fail.
auto [rc, resp] = cc.discoverRegions();
std::cerr << "1/3....rc:" << rc << " Expect failure." << std::endl;
EXPECT_NE(200, rc) << resp.dump(3);
auto rc = cc.discoverRegions();
// std::cerr << "1/3....rc:" << rc << " Expect failure." << std::endl;
EXPECT_NE(200, rc.statusCode) << rc.document.dump(3);

// Try again.. we should succeed.
std::cerr << "......................rotated: " << cc.Cnxn.rotate() << std::endl;
std::tie(rc, resp) = cc.discoverRegions();
std::cerr << "2/3....rc:" << rc << " Expect success." << std::endl;
EXPECT_EQ(200, rc) << resp.dump(3);
cc.Cnxn.rotate();
rc = cc.discoverRegions();
// std::cerr << "2/3....rc:" << rc << " Expect success." << std::endl;
EXPECT_EQ(200, rc.statusCode) << rc.document.dump(3);

// Try again.. we should fail again!
std::cerr << "......................rotated: " << cc.Cnxn.rotate() << std::endl;
std::tie(rc, resp) = cc.discoverRegions();
std::cerr << "3/3....rc:" << rc << " Expect failure." << std::endl;
EXPECT_NE(200, rc) << resp.dump(3);
cc.Cnxn.rotate();
rc = cc.discoverRegions();
// std::cerr << "3/3....rc:" << rc << " Expect failure." << std::endl;
EXPECT_NE(200, rc.statusCode) << rc.document.dump(3);
}


Expand Down Expand Up @@ -294,10 +293,10 @@ TEST(CosmosClient, listDocuments)
ASSERT_FALSE(priConnStr.empty())
<< "Missing environment variable CCTEST_PRIMARY_CS; Set it to Primary Connection string from Azure portal.";

siddiqsoft::CosmosClient cc;
std::string cToken {};
uint32_t totalDocs = 0;
auto iteration = 7; // max 7 times
siddiqsoft::CosmosClient cc;
siddiqsoft::CosmosIterableResponseType irt {};
uint32_t totalDocs = 0;
auto iteration = 7; // max 7 times

cc.configure({{"partitionKeyNames", {"__pk"}}, {"connectionStrings", {priConnStr, secConnStr}}});

Expand All @@ -308,23 +307,18 @@ TEST(CosmosClient, listDocuments)
EXPECT_EQ(200, rc2);

do {
auto [rc3, respDocuments] = cc.listDocuments(resp.value("/Databases/0/id"_json_pointer, ""),
respCollections.value("/DocumentCollections/0/id"_json_pointer, ""),
cToken);
EXPECT_EQ(200, rc3);
// std::cerr << respDocuments.dump(2) << std::endl;
irt = cc.listDocuments(resp.value("/Databases/0/id"_json_pointer, ""),
respCollections.value("/DocumentCollections/0/id"_json_pointer, ""),
irt.continuationToken);
EXPECT_EQ(200, irt.statusCode);
// We check against a collection that has multiple
totalDocs += respDocuments.value<uint32_t>("_count", 0);
EXPECT_EQ(100, respDocuments.value("_count", 0));
EXPECT_FALSE(cToken.empty());
std::cerr << "Read: " << respDocuments.value("_count", 0) << " Culumative: " << totalDocs
<< " -- first:" << respDocuments.value("/Documents/0/id"_json_pointer, "") << std::endl;
totalDocs += irt.document.value<uint32_t>("_count", 0);
EXPECT_EQ(100, irt.document.value("_count", 0));
EXPECT_FALSE(irt.continuationToken.empty());

// If we run out of the iterations the break out of the loop.
if (--iteration == 0) break;
} while (!cToken.empty());

std::cerr << "Total Documents found: " << totalDocs << std::endl;
} while (!irt.continuationToken.empty());
}


Expand All @@ -341,9 +335,9 @@ TEST(CosmosClient, listDocuments_top100)
ASSERT_FALSE(priConnStr.empty())
<< "Missing environment variable CCTEST_PRIMARY_CS; Set it to Primary Connection string from Azure portal.";

siddiqsoft::CosmosClient cc;
std::string cToken {};
uint32_t totalDocs = 0;
siddiqsoft::CosmosClient cc;
siddiqsoft::CosmosIterableResponseType irt {};
uint32_t totalDocs = 0;

cc.configure({{"partitionKeyNames", {"__pk"}}, {"connectionStrings", {priConnStr, secConnStr}}});

Expand All @@ -353,17 +347,14 @@ TEST(CosmosClient, listDocuments_top100)
auto [rc2, respCollections] = cc.listCollections(resp.value("/Databases/0/id"_json_pointer, ""));
EXPECT_EQ(200, rc2);

auto [rc3, respDocuments] = cc.listDocuments(resp.value("/Databases/0/id"_json_pointer, ""),
respCollections.value("/DocumentCollections/0/id"_json_pointer, ""),
cToken);
EXPECT_EQ(200, rc3);
// std::cerr << respDocuments.dump(2) << std::endl;
irt = cc.listDocuments(resp.value("/Databases/0/id"_json_pointer, ""),
respCollections.value("/DocumentCollections/0/id"_json_pointer, ""),
irt.continuationToken);
EXPECT_EQ(200, irt.statusCode);
// We check against a collection that has multiple
totalDocs += respDocuments.value<uint32_t>("_count", 0);
EXPECT_EQ(100, respDocuments.value("_count", 0));
EXPECT_FALSE(cToken.empty());
std::cerr << "Read: " << respDocuments.value("_count", 0) << " Culumative: " << totalDocs
<< " -- first:" << respDocuments.value("/Documents/0/id"_json_pointer, "") << std::endl;
totalDocs += irt.document.value<uint32_t>("_count", 0);
EXPECT_EQ(100, irt.document.value("_count", 0));
EXPECT_FALSE(irt.continuationToken.empty());
}


Expand Down Expand Up @@ -405,7 +396,7 @@ TEST(CosmosClient, createDocument)
cc.create(dbName, collectionName, {{"id", docId}, {"ttl", 360}, {"__pk", pkId}, {"source", "basic_tests.exe"}});
EXPECT_EQ(201, rc3);

auto [rc4, delDoc] = cc.remove(dbName, collectionName, docId, pkId);
auto rc4 = cc.remove(dbName, collectionName, docId, pkId);
EXPECT_EQ(204, rc4);
}

Expand Down Expand Up @@ -527,9 +518,8 @@ TEST(CosmosClient, findDocument)
auto [rc4, findDoc] = cc.find(dbName, collectionName, docId, pkId);
EXPECT_EQ(200, rc4);
EXPECT_EQ(docId, findDoc.value("id", ""));
std::cerr << findDoc.dump(3) << std::endl;

auto [rc5, delDoc] = cc.remove(dbName, collectionName, docId, pkId);
auto rc5 = cc.remove(dbName, collectionName, docId, pkId);
EXPECT_EQ(204, rc5);
}

Expand Down Expand Up @@ -586,13 +576,14 @@ TEST(CosmosClient, upsertDocument)
auto rc6 = cc.create(dbName,
collectionName,
{{"id", docId}, {"ttl", 360}, {"__pk", pkId}, {"upsert", "FAIL"}, {"source", "basic_tests.exe"}});
EXPECT_EQ(409, std::get<0>(rc6));
EXPECT_EQ(409, rc6.statusCode);

// Remove the document
auto rc7 = cc.remove(dbName, collectionName, docId, pkId);
EXPECT_EQ(204, std::get<0>(rc7));
EXPECT_EQ(204, rc7);
}


/// @brief Test query API
TEST(CosmosClient, queryDocument)
{
Expand Down Expand Up @@ -639,58 +630,93 @@ TEST(CosmosClient, queryDocument)
{"odd", !(i % 2 == 0)},
{"source", sourceId}});
EXPECT_EQ(201, rc);
std::cerr << "**** Created: " << docIds[i] << "--" << sourceId << std::endl;
// std::cerr << "**** Created: " << docIds[i] << "--" << sourceId << std::endl;
}

EXPECT_EQ(DOCS, docIds.size()); // total

// Wait a little bit..
std::this_thread::sleep_for(std::chrono::seconds(1));

siddiqsoft::CosmosIterableResponseType irt {};
nlohmann::json allDocs = nlohmann::json::array();
uint32_t allDocsCount {};

// First, we query for all items that match our criteria (source=__func__)
auto [rq1, qDoc1] =
cc.query(dbName,
collectionName,
"*",
"SELECT * FROM c WHERE contains(c.source, @v1)",
{{{"name", "@v1"}, {"value", std::format("{}-", getpid())}}}); // the params is an array of name-value items
EXPECT_EQ(200, rq1);
EXPECT_EQ(DOCS, qDoc1.value("_count", 0)); // total
do {
irt = cc.query(dbName,
collectionName,
"*",
"SELECT * FROM c WHERE contains(c.source, @v1)",
{{{"name", "@v1"}, {"value", std::format("{}-", getpid())}}},
irt.continuationToken); // the params is an array of name-value items
EXPECT_EQ(200, irt.statusCode);
if (200 == irt.statusCode && irt.document.contains("Documents") && !irt.document.at("Documents").is_null()) {
// Append to the current container
allDocs.insert(allDocs.end(), irt.document["Documents"].begin(), irt.document["Documents"].end());
allDocsCount += irt.document.value("_count", 0);
}
} while (!irt.continuationToken.empty());
EXPECT_EQ(DOCS, allDocsCount); // total

#ifdef _DEBUG
std::cerr << allDocs.dump(4) << std::endl;
#endif

auto matchCount = 0;
for (auto& doc : qDoc1["Documents"]) {
auto& docId = doc.at("id");
std::cerr << "Matched " << 1 + matchCount << " from query docId:" << doc.value("id", "") << std::endl;
std::for_each(docIds.begin(), docIds.end(), [&matchCount, &docId](auto& i) {
if (i == docId) matchCount++;
});
for (auto& doc : allDocs) {
if (!doc.is_null()) {
auto& docId = doc.at("id");
std::for_each(docIds.begin(), docIds.end(), [&matchCount, &docId](auto& i) {
if (i == docId) matchCount++;
});
}
}
EXPECT_EQ(DOCS, matchCount);

// Clear stuff..
irt.continuationToken.clear();
allDocs = nlohmann::json::array();
allDocsCount = 0;
// Query with partition key "odd"; out of five, 2 should be odd: 1, 3
auto [rq2, qDoc2] = cc.query(dbName,
collectionName,
"odd.siddiqsoft.com", // __pk
"SELECT * FROM c WHERE c.source=@v1",
{{{"name", "@v1"}, {"value", sourceId}}});
EXPECT_EQ(200, rq2);
EXPECT_EQ(2, qDoc2.value("_count", 0)); // odd
do {
irt = cc.query(dbName,
collectionName,
"odd.siddiqsoft.com", // __pk
"SELECT * FROM c WHERE c.source=@v1",
{{{"name", "@v1"}, {"value", sourceId}}});
EXPECT_EQ(200, irt.statusCode);
if (irt.document.contains("Documents") && !irt.document.at("Documents").is_null())
allDocs.insert(allDocs.end(), irt.document["Documents"].begin(), irt.document["Documents"].end());
allDocsCount += irt.document.value("_count", 0);
} while (!irt.continuationToken.empty());
EXPECT_EQ(2, allDocsCount); // odd

// Query with partition key "odd"; out of five, 3 should be even: 0, 2
auto [rq3, qDoc3] = cc.query(dbName,
collectionName,
"even.siddiqsoft.com", // __pk
"SELECT * FROM c WHERE c.source=@v1",
{{{"name", "@v1"}, {"value", sourceId}}});
EXPECT_EQ(200, rq3);
EXPECT_EQ(3, qDoc3.value("_count", 0)); // even
// Clear stuff..
irt.continuationToken.clear();
allDocs = nlohmann::json::array();
allDocsCount = 0;
// Query with partition key "odd"; out of five, 2 should be odd: 1, 3
do {
irt = cc.query(dbName,
collectionName,
"even.siddiqsoft.com", // __pk
"SELECT * FROM c WHERE c.source=@v1",
{{{"name", "@v1"}, {"value", sourceId}}});
EXPECT_EQ(200, irt.statusCode);
if (irt.document.contains("Documents") && !irt.document.at("Documents").is_null())
allDocs.insert(allDocs.end(), irt.document["Documents"].begin(), irt.document["Documents"].end());
allDocsCount += irt.document.value("_count", 0);
} while (!irt.continuationToken.empty());
EXPECT_EQ(3, allDocsCount); // even

// Wait a little bit..
std::this_thread::sleep_for(std::chrono::seconds(2));

// Remove the documents
for (auto i = 0; i < docIds.size(); i++) {
auto [rc, _] = cc.remove(dbName, collectionName, docIds[i], (i % 2 == 0) ? "even.siddiqsoft.com" : "odd.siddiqsoft.com");
auto rc = cc.remove(dbName, collectionName, docIds[i], (i % 2 == 0) ? "even.siddiqsoft.com" : "odd.siddiqsoft.com");
EXPECT_EQ(204, rc);
}
}
Loading

0 comments on commit efc4e49

Please sign in to comment.