Add transaction tests and documentations (#164)

Signed-off-by: Tao He <sighingnow@gmail.com>
This commit is contained in:
Tao He 2022-09-27 11:31:06 +08:00 committed by GitHub
parent 92efa7c9de
commit 1108d986a7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 121 additions and 0 deletions

View File

@ -172,6 +172,9 @@ jobs:
echo "Run the etcd watcher test ........................." echo "Run the etcd watcher test ........................."
./build/bin/WatcherTest ./build/bin/WatcherTest
echo "Run the etcd transaction test ........................."
./build/bin/TransactionTest
echo "Run the etcd election test ........................." echo "Run the etcd election test ........................."
./build/bin/ElectionTest ./build/bin/ElectionTest

View File

@ -756,6 +756,35 @@ is constructed.
Without handler, the internal state can be checked via `KeepAlive::Check()` and it will rethrow Without handler, the internal state can be checked via `KeepAlive::Check()` and it will rethrow
the async exception when there are errors during keeping the lease alive. the async exception when there are errors during keeping the lease alive.
### Etcd transactions
Etcd v3's [Transaction APIs](https://etcd.io/docs/v3.4/learning/api/#transaction) is supported via the
`etcdv3::Transaction` interfaces. A set of convenient APIs are use to add operations to a transaction, e.g.,
```cpp
etcdv3::Transaction txn;
txn.setup_put("/test/x1", "1");
txn.setup_put("/test/x2", "2");
txn.setup_put("/test/x3", "3");
etcd::Response resp = etcd.txn(txn).get();
```
Transactions in etcd supports set a set of comparison targets to specify the condition of transaction, e.g.,
```cpp
etcdv3::Transaction txn;
// setup the conditions
txn.reset_key("/test/x1");
txn.init_compare("1", etcdv3::CompareResult::EQUAL, etcdv3::CompareTarget::VALUE);
txn.reset_key("/test/x2");
txn.init_compare("2", etcdv3::CompareResult::EQUAL, etcdv3::CompareTarget::VALUE);
```
See full example of the usages of transaction APIs, please refer to [./tst/TransactionTest.cpp](./tst/TransactionTest.cpp),
for full list of the transaction operation APIs, see [./etcd/v3/Transaction.hpp](./etcd/v3/Transaction.hpp).
### Election API ### Election API
Etcd v3's [election APIs](https://github.com/etcd-io/etcd/blob/main/server/etcdserver/api/v3election/v3electionpb/v3election.proto) Etcd v3's [election APIs](https://github.com/etcd-io/etcd/blob/main/server/etcdserver/api/v3election/v3electionpb/v3election.proto)

89
tst/TransactionTest.cpp Normal file
View File

@ -0,0 +1,89 @@
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <chrono>
#include <iostream>
#include <thread>
#include "etcd/Client.hpp"
#include "etcd/v3/Transaction.hpp"
TEST_CASE("setup")
{
etcd::Client etcd("http://127.0.0.1:2379");
etcd.rmdir("/test", true).wait();
}
TEST_CASE("add a new key")
{
etcd::Client etcd("http://127.0.0.1:2379");
etcd.rmdir("/test", true).wait();
// do some put using txn
{
etcdv3::Transaction txn;
txn.setup_put("/test/x1", "1");
txn.setup_put("/test/x2", "2");
txn.setup_put("/test/x3", "3");
etcd::Response resp = etcd.txn(txn).get();
REQUIRE(0 == resp.error_code());
}
// check the value
{
etcd::Response resp = etcd.get("/test/x1").get();
REQUIRE(0 == resp.error_code());
CHECK(resp.value().as_string() == "1");
resp = etcd.get("/test/x2").get();
REQUIRE(0 == resp.error_code());
CHECK(resp.value().as_string() == "2");
resp = etcd.get("/test/x3").get();
REQUIRE(0 == resp.error_code());
CHECK(resp.value().as_string() == "3");
}
// do some put and delete using txn
{
etcdv3::Transaction txn;
// setup the conditions
txn.reset_key("/test/x1");
txn.init_compare("1", etcdv3::CompareResult::EQUAL, etcdv3::CompareTarget::VALUE);
txn.reset_key("/test/x2");
txn.init_compare("2", etcdv3::CompareResult::EQUAL, etcdv3::CompareTarget::VALUE);
txn.setup_put("/test/x1", "111");
txn.setup_delete("/test/x2");
txn.setup_delete("/test/x3");
txn.setup_put("/test/x4", "4");
etcd::Response resp = etcd.txn(txn).get();
REQUIRE(0 == resp.error_code());
}
// check the value
{
etcd::Response resp = etcd.get("/test/x1").get();
REQUIRE(0 == resp.error_code());
CHECK(resp.value().as_string() == "111");
resp = etcd.get("/test/x2").get();
REQUIRE(etcdv3::ERROR_KEY_NOT_FOUND == resp.error_code());
resp = etcd.get("/test/x3").get();
REQUIRE(etcdv3::ERROR_KEY_NOT_FOUND == resp.error_code());
resp = etcd.get("/test/x4").get();
REQUIRE(0 == resp.error_code());
CHECK(resp.value().as_string() == "4");
}
}
TEST_CASE("cleanup")
{
etcd::Client etcd("http://127.0.0.1:2379");
REQUIRE(0 == etcd.rmdir("/test", true).get().error_code());
}