From 65271bb92df41f5208d3b5f3bee7a85d37ba3045 Mon Sep 17 00:00:00 2001 From: Tao He Date: Thu, 1 Oct 2020 01:47:43 +0800 Subject: [PATCH] Enhance tests and improve documents about about build & install. Should fixes #2, #4. Signed-off-by: Tao He --- .github/workflows/build-test.yml | 2 +- README.md | 210 ++++++++++++++++--------------- tst/CMakeLists.txt | 28 +++-- tst/EtcdSyncTest.cpp | 124 +++++++++--------- tst/EtcdTest.cpp | 27 +--- tst/LockTest.cpp | 5 +- tst/WatcherTest.cpp | 15 +-- 7 files changed, 201 insertions(+), 210 deletions(-) diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 51f25ac..9e7f011 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -86,7 +86,7 @@ jobs: run: | cd build /usr/local/bin/etcd & - ./bin/etcd_test + CTEST_OUTPUT_ON_FAILURE=1 make test # note: no need to clean up on CI env diff --git a/README.md b/README.md index efc8b65..866f4bf 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,38 @@ -etcd-cpp-api is a C++ API for [etcd] +etcd-cpp-apiv3 +============== + +The _etcd-cpp-apiv3_ is a C++ API for [etcd](https://etcd.io/)'s v3 client API, +i.e., `ETCDCTL_API=3`. ## Requirements -1. Build Boost Library(http://www.boost.org/doc/libs/1_61_0/more/getting_started/unix-variants.html) - * You can use: - ``` - ./bootstrap.sh --with-libraries=system,thread,locale,random,chrono,regex,filesystem - ./b2 install - ``` - * The above command will only compile those libraries indicated, thus it takes less time to build boost -2. Build Casablanca: - * Instructions on how to build is here: https://github.com/Microsoft/cpprestsdk/wiki - * For Linux environment you can omit libboost-all-dev during apt-get install, if you already have boost library installed. +1. boost +2. protobuf +3. gRPC +4. [cpprestsdk](https://github.com/microsoft/cpprestsdk), the latest version of master branch + on github should work, you can build and install this dependency using cmake with: -3. Install Protobuf: - * https://github.com/google/protobuf/blob/master/src/README.md + git clone https://github.com/microsoft/cpprestsdk.git + cd cpprestsdk + mkdir build && cd build + cmake .. -DCPPREST_EXCLUDE_WEBSOCKETS=ON + make -j && make install -4. Install Protoc for C++: - * https://github.com/grpc/grpc/blob/release-0_14/INSTALL.md +## Build and install + +The _etcd-cpp-apiv3_ library could be easily built and installed using cmake, after all above +dependencies have been successfully installed: + + mkdir build && cd build + cmake .. + make -j - ## Compatible etcd version -Build master branch of etcd in github. As of writing, current releases of etcd does not yet support prev_value. -Only the master branch supports it. -https://github.com/coreos/etcd/blob/master/Documentation/dl_build.md (see: Build the latest version) -## Updates from etcdv2 cpp client to etcdv3 cpp client -See "handling directory nodes" section +The _etcd-cpp-apiv3_ should work well with etcd > 3.0. Feel free to issue an issue to us on +Github when you encounter problems when working with etcd 3.x releases. -## compiling .proto -Proto files are stored in /proto. The proto files defined the interface of etcdv3. - -You can compile it like this(if you are running this command inside /proto folder): -``` -protoc -I . --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ./rpc.proto -protoc -I . --cpp_out=. ./*.proto -``` - -Protofiles for etcdv3 can be found here: -* https://github.com/coreos/etcd/tree/master/auth/authpb -* https://github.com/coreos/etcd/tree/master/etcdserver/etcdserverpb -* https://github.com/coreos/etcd/tree/master/mvcc/mvccpb - -Note: Protofiles in the project is not sync to the protofiles in etcd master branch. If you -want to update the protofiles in this project, you need to manually update it. - -## generic notes +## Usage ```c++ etcd::Client etcd("http://127.0.0.1:4001"); @@ -64,7 +51,7 @@ also returns the ```etcd::Response``` object. ```c++ etcd::Client etcd("http://127.0.0.1:4001"); - pplx::task response_task = etcd.get("/test/key1").get(); + pplx::task response_task = etcd.get("/test/key1"); // ... do something else etcd::Response response = response_task.get(); std::cout << response.value().as_string(); @@ -113,7 +100,7 @@ this case since the respose has been already arrived (we are inside the callback ## etcd operations -### reading a value +### Reading a value You can read a value with the ```get``` method of the clinent instance. The only parameter is the key to be read. If the read operation is successful then the value of the key can be acquired with @@ -149,7 +136,7 @@ the ```created_index()``` and the ```modofied_index()``` methods. } ``` -### modifying a value +### Modifying a value Setting the value of a key can be done with the ```set()``` method of the client. You simply pass the key and the value as string parameters and you are done. The newly set value object can be asked @@ -192,7 +179,7 @@ some specific conditions. the previous value equals with old_index. If the indices does not match returns with "Compare failed" error (code 101) -### deleting a value +### Deleting a value Values can be deleted with the ```rm``` method passing the key to be deleted as a parameter. The key should point to an existing value. There are conditional variations for deletion too. @@ -204,57 +191,67 @@ should point to an existing value. There are conditional variations for deletion the previous value equals with old_index. If the indices does not match returns with "Compare failed" error (code 101) -### handling directory nodes -Directory nodes are not supported anymore in etcdv3. +### Handling directory nodes -However, ls and rmdir will list/delete keys defined by the prefix. mkdir method is removed since -etcdv3 treats everything as keys. +Directory nodes are not supported anymore in etcdv3. However, ls and rmdir will list/delete +keys defined by the prefix. mkdir method is removed since etcdv3 treats everything as keys. 1. Creating a directory: -Creating a directory is not supported anymore in etcdv3 cpp client. Users should remove the -API from their code. + + Creating a directory is not supported anymore in etcdv3 cpp client. Users should remove the + API from their code. 2. Listing a directory: -Listing directory in etcd3 cpp client will return all keys that matched the given prefix recursively. -```c++ - etcd.set("/test/key1", "value1").wait(); - etcd.set("/test/key2", "value2").wait(); - etcd.set("/test/key3", "value3").wait(); - etcd.set("/test/subdir/foo", "foo").wait(); - - etcd::Response resp = etcd.ls("/test/new_dir").get(); -``` -resp.key() will have the following values: -/test/key1 -/test/key2 -/test/key3 -/test/subdir/foo + Listing directory in etcd3 cpp client will return all keys that matched the given prefix + recursively. + ```c++ + etcd.set("/test/key1", "value1").wait(); + etcd.set("/test/key2", "value2").wait(); + etcd.set("/test/key3", "value3").wait(); + etcd.set("/test/subdir/foo", "foo").wait(); -Note: Regarding the returned keys when listing a directory: -In etcdv3 cpp client, resp.key(0) will return "/test/new_dir/key1" since everything is treated as keys in etcdv3. -While in etcdv2 cpp client it will return "key1" and "/test/new_dir" directory should be created first before you can set "key1". + etcd::Response resp = etcd.ls("/test/new_dir").get(); + ``` -When you list a directory the response object's ```keys()``` and ```values()``` methods gives you a -vector of key names and values. The ```value()``` method with an integer parameter also -returns with the i-th element of the values vector, so ```response.values()[i] == -response.value(i)```. + ```resp.key()``` will have the following values: -```c++ - etcd::Client etcd("http://127.0.0.1:4001"); - etcd::Response resp = etcd.ls("/test/new_dir").get(); - for (int i = 0; i < resp.keys().size(); ++i) - { - std::cout << resp.keys(i); - std::cout << " = " << resp.value(i).as_string() << std::endl; - } -``` + ``` + /test/key1 + /test/key2 + /test/key3 + /test/subdir/foo + ``` + + Note: Regarding the returned keys when listing a directory: + + + In etcdv3 cpp client, resp.key(0) will return "/test/new_dir/key1" since everything is + treated as keys in etcdv3. + + While in etcdv2 cpp client it will return "key1" and "/test/new_dir" directory should + be created first before you can set "key1". + + When you list a directory the response object's ```keys()``` and ```values()``` methods gives + you a vector of key names and values. The ```value()``` method with an integer parameter also + returns with the i-th element of the values vector, so ```response.values()[i] == + response.value(i)```. + + ```c++ + etcd::Client etcd("http://127.0.0.1:4001"); + etcd::Response resp = etcd.ls("/test/new_dir").get(); + for (int i = 0; i < resp.keys().size(); ++i) + { + std::cout << resp.keys(i); + std::cout << " = " << resp.value(i).as_string() << std::endl; + } + ``` 3. Removing directory: -If you want the delete recursively then you have to pass a second ```true``` parameter -to rmdir and supply a key. This key will be treated as a prefix. All keys that match the prefix will -be deleted. All deleted keys will be placed in response.values() and response.keys(). This parameter defaults to ```false```. + +If you want the delete recursively then you have to pass a second ```true``` parameter +to rmdir and supply a key. This key will be treated as a prefix. All keys that match the +prefix will be deleted. All deleted keys will be placed in ```response.values()``` and +```response.keys()```. This parameter defaults to ```false```. ```c++ etcd::Client etcd("http://127.0.0.1:4001"); @@ -266,13 +263,13 @@ be deleted. All deleted keys will be placed in response.values() and response.ke { std::cout << resp.keys(i); std::cout << " = " << resp.value(i).as_string() << std::endl; - } - + } ``` + However, if recursive parameter is false, functionality will be the same as just deleting a key. The key supplied will NOT be treated as a prefix and will be treated as a normal key name. -### watching for changes +### Watching for changes Watching for a change is possible with the ```watch()``` operation of the client. The watch method simply does not deliver a response object until the watched value changes in any way (modified or @@ -283,12 +280,15 @@ value and ```response.prev_value()``` will contain the previous value. In case o ```response.action()``` will return "delete", ```response.value()``` will be empty and should not be called at all and ```response.prev_value()``` will contain the deleted value. -As mentioned in the section "handling directory nodes", directory nodes are not supported anymore in etcdv3. -However it is still possible to watch a whole "directory subtree", or more specifically a set of keys that match the -prefix, for changes with passing ```true``` to the second ```recursive``` parameter of ```watch``` -(this parameter defaults to ```false``` if omitted). In this case the modified value object's ```key()``` method can be -handy to determine what key is actually changed. Since this can be a long lasting operation you have to be prepared that is -terminated by an exception and you have to restart the watch operation. +As mentioned in the section "handling directory nodes", directory nodes are not supported anymore +in etcdv3. + +However it is still possible to watch a whole "directory subtree", or more specifically a set of +keys that match the prefix, for changes with passing ```true``` to the second ```recursive``` +parameter of ```watch``` (this parameter defaults to ```false``` if omitted). In this case the +modified value object's ```key()``` method can be handy to determine what key is actually changed. +Since this can be a long lasting operation you have to be prepared that is terminated by an +exception and you have to restart the watch operation. The watch also accepts an index parameter that specifies what is the first change we are interested about. Since etcd stores the last couple of modifications with this feature you can ensure that your @@ -314,44 +314,48 @@ void watch_for_changes() ``` At first glance it seems that ```watch_for_changes()``` calls itself on every value change but in -fact it just sends the asynchron request, sets up a callback for the response and then returns. The +fact it just sends the asynchron request, sets up a callback for the response and then returns. The callback is executed by some thread from the pplx library's thread pool and the callback (in this case a small lambda function actually) will call ```watch_for_changes``` again from there. -### requesting for lease +### Requesting for lease + Users can request for lease which is governed by a time-to-live(TTL) value given by the user. -Moreover, user can attached the lease to a key(s) by indicating the lease id in add(), set(), modify() and modify_if(). -Also the ttl will that was granted by etcd server will be indicated in ttl(). +Moreover, user can attached the lease to a key(s) by indicating the lease id in ```add()```, +```set()```, ```modify()``` and ```modify_if()```. Also the ttl will that was granted by etcd +server will be indicated in ```ttl()```. ```c++ etcd::Client etcd("http://127.0.0.1:4001"); etcd::Response resp = etcd.leasegrant(60).get(); etcd.set("/test/key2", "bar", resp.value().lease()); std::cout <<"ttl" << resp.value().ttl(); - ``` ### Watcher Class -Users can watch a key indefinitely or until user cancels the watch. This can be done by instantiating a Watcher class. -The supplied callback function in Watcher class will be called every time there is an event for the specified key. -Watch stream will be cancelled either by user implicitly calling Cancel() or when watcher class is destroyed. + +Users can watch a key indefinitely or until user cancels the watch. This can be done by +instantiating a Watcher class. The supplied callback function in Watcher class will be +called every time there is an event for the specified key. Watch stream will be cancelled +either by user implicitly calling ```Cancel()``` or when watcher class is destroyed. ```c++ etcd::Watcher watcher("http://127.0.0.1:2379", "/test", printResponse); etcd.set("/test/key", "42"); /* print response will be called */ etcd.set("/test/key", "43"); /* print response will be called */ watcher.Cancel(); - etcd.set("/test/key", "43"); /* print response will NOT be called, since watch is already cancelled */ + etcd.set("/test/key", "43"); /* print response will NOT be called, + since watch is already cancelled */ } ``` ### TODO + 1. Cancellation of asynchronous calls(except for watch) 2. LeaseKeepAlive - - +3. Authentication ## License -This project is licensed under the BSD-3-Clause license - see the [LICENSE](https://github.com/nokia/etcd-cpp-apiv3/blob/master/LICENSE.txt). \ No newline at end of file +This project is licensed under the BSD-3-Clause license - see the [LICENSE](https://github.com/etcd-cpp-apiv3/etcd-cpp-apiv3/blob/master/LICENSE.txt). diff --git a/tst/CMakeLists.txt b/tst/CMakeLists.txt index a4e0ee2..301302c 100644 --- a/tst/CMakeLists.txt +++ b/tst/CMakeLists.txt @@ -1,16 +1,22 @@ find_path(CATCH_INCLUDE_DIR NAMES catch.hpp PATHS ${PROJECT_SOURCE_DIR}) include_directories(${CATCH_INCLUDE_DIR}) -add_executable(etcd_test - EtcdTest.cpp - EtcdSyncTest.cpp - WatcherTest.cpp - LockTest.cpp -) -set_property(TARGET etcd_test PROPERTY CXX_STANDARD 11) -target_include_directories(etcd_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../proto/gen) -target_include_directories(etcd_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../proto/gen/proto) +add_custom_target(check ${CMAKE_COMMAND} -E env CTEST_OUTPUT_ON_FAILURE=1 + ${CMAKE_CTEST_COMMAND} -C $ --verbose + WORKING_DIRECTORY ${PROJECT_BINARY_DIR}) -target_link_libraries(etcd_test etcd-cpp-api) +file(GLOB TEST_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp") +foreach(testfile ${TEST_FILES}) + string(REGEX MATCH "^(.*)\\.[^.]*$" dummy ${testfile}) + set(test_name ${CMAKE_MATCH_1}) + message(STATUS "Found unit_test - " ${test_name}) + add_executable(${test_name} ${CMAKE_CURRENT_SOURCE_DIR}/${testfile}) + add_test(NAME ${test_name} COMMAND $) -add_test(etcd_test etcd_test) + set_property(TARGET ${test_name} PROPERTY CXX_STANDARD 11) + target_include_directories(${test_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../proto/gen) + target_include_directories(${test_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../proto/gen/proto) + target_link_libraries(${test_name} etcd-cpp-api) + + add_dependencies(check ${test_name}) +endforeach() diff --git a/tst/EtcdSyncTest.cpp b/tst/EtcdSyncTest.cpp index 6a5352f..295ab2f 100644 --- a/tst/EtcdSyncTest.cpp +++ b/tst/EtcdSyncTest.cpp @@ -1,3 +1,4 @@ +#define CATCH_CONFIG_MAIN #include #include "etcd/SyncClient.hpp" @@ -24,25 +25,26 @@ TEST_CASE("sync operations") CHECK(0 == etcd.set("/test/key2", "43").error_code()); // create new CHECK("43" == etcd.set("/test/key2", "44").prev_value().as_string()); CHECK("" == etcd.set("/test/key3", "44").prev_value().as_string()); - //CHECK(102 == etcd.set("/test", "42").error_code()); // Not a file + + // get + CHECK("43" == etcd.get("/test/key1").value().as_string()); + CHECK("44" == etcd.get("/test/key2").value().as_string()); + CHECK("44" == etcd.get("/test/key3").value().as_string()); + CHECK(100 == etcd.get("/test/key4").error_code()); // key not found // rm CHECK(3 == etcd.ls("/test").keys().size()); CHECK(0 == etcd.rm("/test/key1").error_code()); CHECK(2 == etcd.ls("/test").keys().size()); - // mkdir - //CHECK(etcd.mkdir("/test/new_dir").value().is_dir()); - // ls CHECK(0 == etcd.ls("/test/new_dir").keys().size()); etcd.set("/test/new_dir/key1", "value1"); etcd.set("/test/new_dir/key2", "value2"); - //etcd.mkdir("/test/new_dir/sub_dir"); CHECK(2 == etcd.ls("/test/new_dir").keys().size()); // rmdir - //CHECK(108 == etcd.rmdir("/test/new_dir").error_code()); // Directory not empty + CHECK(100 == etcd.rmdir("/test/new_dir").error_code()); // key not found CHECK(0 == etcd.rmdir("/test/new_dir", true).error_code()); // compare and swap @@ -102,64 +104,74 @@ TEST_CASE("sync operations") CHECK(leaseid == res.value().lease()); CHECK("44" == res.value().as_string()); -// TEST_CASE("wait for a value change") -// { -// etcd::Client etcd(etcd_uri); -// etcd.set("/test/key1", "42").wait(); + REQUIRE(0 == etcd.rmdir("/test", true).error_code()); +} -// pplx::task res = etcd.watch("/test/key1"); -// CHECK(!res.is_done()); +TEST_CASE("wait for a value change") +{ + etcd::Client etcd(etcd_uri); + etcd.set("/test/key1", "42").wait(); -// etcd.set("/test/key1", "43").get(); -// sleep(1); + pplx::task res = etcd.watch("/test/key1"); + CHECK(!res.is_done()); -// REQUIRE(res.is_done()); -// REQUIRE("set" == res.get().action()); -// CHECK("43" == res.get().value().as_string()); -// } + etcd.set("/test/key1", "43").get(); + sleep(1); -// TEST_CASE("wait for a directory change") -// { -// etcd::Client etcd(etcd_uri); + REQUIRE(res.is_done()); + REQUIRE("set" == res.get().action()); + CHECK("43" == res.get().value().as_string()); -// pplx::task res = etcd.watch("/test", true); + REQUIRE(0 == etcd.rmdir("/test", true).get().error_code()); +} -// etcd.add("/test/key4", "44").wait(); -// REQUIRE(res.is_done()); -// CHECK("create" == res.get().action()); -// CHECK("44" == res.get().value().as_string()); +TEST_CASE("wait for a directory change") +{ + etcd::Client etcd(etcd_uri); -// pplx::task res2 = etcd.watch("/test", true); + pplx::task res = etcd.watch("/test", true); -// etcd.set("/test/key4", "45").wait(); -// sleep(1); -// REQUIRE(res2.is_done()); -// CHECK("set" == res2.get().action()); -// CHECK("45" == res2.get().value().as_string()); -// } + etcd.add("/test/key4", "44").wait(); + sleep(1); + REQUIRE(res.is_done()); + CHECK("create" == res.get().action()); + CHECK("44" == res.get().value().as_string()); -// TEST_CASE("watch changes in the past") -// { -// etcd::Client etcd(etcd_uri); + pplx::task res2 = etcd.watch("/test", true); -// int index = etcd.set("/test/key1", "42").get().index(); + etcd.set("/test/key4", "45").wait(); + sleep(1); + REQUIRE(res2.is_done()); + CHECK("set" == res2.get().action()); + CHECK("45" == res2.get().value().as_string()); -// etcd.set("/test/key1", "43").wait(); -// etcd.set("/test/key1", "44").wait(); -// etcd.set("/test/key1", "45").wait(); + REQUIRE(0 == etcd.rmdir("/test", true).get().error_code()); +} -// etcd::Response res = etcd.watch("/test/key1", ++index).get(); -// CHECK("set" == res.action()); -// CHECK("43" == res.value().as_string()); +TEST_CASE("watch changes in the past") +{ + etcd::Client etcd(etcd_uri); -// res = etcd.watch("/test/key1", ++index).get(); -// CHECK("set" == res.action()); -// CHECK("44" == res.value().as_string()); + int index = etcd.set("/test/key1", "42").get().index(); -// res = etcd.watch("/test", ++index, true).get(); -// CHECK("set" == res.action()); -// CHECK("45" == res.value().as_string()); -// } + etcd.set("/test/key1", "43").wait(); + etcd.set("/test/key1", "44").wait(); + etcd.set("/test/key1", "45").wait(); + + etcd::Response res = etcd.watch("/test/key1", ++index).get(); + CHECK("set" == res.action()); + CHECK("43" == res.value().as_string()); + + res = etcd.watch("/test/key1", ++index).get(); + CHECK("set" == res.action()); + CHECK("44" == res.value().as_string()); + + res = etcd.watch("/test", ++index, true).get(); + CHECK("set" == res.action()); + CHECK("45" == res.value().as_string()); + + REQUIRE(0 == etcd.rmdir("/test", true).get().error_code()); +} // TEST_CASE("request cancellation") // { @@ -173,19 +185,13 @@ TEST_CASE("sync operations") // sleep(1); // REQUIRE(res.is_done()); -// try -// { +// try { // res.wait(); // } -// catch(pplx::task_canceled const & ex) -// { +// catch(pplx::task_canceled const & ex) { // std::cout << "pplx::task_canceled: " << ex.what() << "\n"; // } -// catch(std::exception const & ex) -// { +// catch(std::exception const & ex) { // std::cout << "std::exception: " << ex.what() << "\n"; // } // } - - REQUIRE(0 == etcd.rmdir("/test", true).error_code()); -} diff --git a/tst/EtcdTest.cpp b/tst/EtcdTest.cpp index a0b6649..ee26141 100644 --- a/tst/EtcdTest.cpp +++ b/tst/EtcdTest.cpp @@ -1,5 +1,6 @@ #define CATCH_CONFIG_MAIN #include + #include #include "etcd/Client.hpp" @@ -11,10 +12,8 @@ TEST_CASE("setup") 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(); etcd::Response resp = etcd.add("/test/key1", "42").get(); @@ -32,7 +31,6 @@ TEST_CASE("add a new key") CHECK("Key already exists" == etcd.add("/test/key1", "42").get().error_message()); } - TEST_CASE("read a value from etcd") { etcd::Client etcd("http://127.0.0.1:2379"); @@ -41,11 +39,9 @@ TEST_CASE("read a value from etcd") REQUIRE(resp.is_ok()); REQUIRE(0 == resp.error_code()); CHECK("42" == resp.value().as_string()); - CHECK("" == etcd.get("/test").get().value().as_string()); // key points to a directory } - TEST_CASE("simplified read") { etcd::Client etcd("http://127.0.0.1:2379"); @@ -54,8 +50,6 @@ TEST_CASE("simplified read") CHECK("" == etcd.get("/test/key2").get().value().as_string()); // Key not found } - - TEST_CASE("modify a key") { etcd::Client etcd("http://127.0.0.1:2379"); @@ -66,7 +60,6 @@ TEST_CASE("modify a key") CHECK("43" == etcd.modify("/test/key1", "42").get().prev_value().as_string()); } - TEST_CASE("set a key") { etcd::Client etcd("http://127.0.0.1:2379"); @@ -110,10 +103,8 @@ TEST_CASE("atomic compare-and-swap") CHECK(!res.is_ok()); CHECK(100 == res.error_code()); CHECK("Key not found" == res.error_message()); - } - TEST_CASE("delete a value") { etcd::Client etcd("http://127.0.0.1:2379"); @@ -188,7 +179,6 @@ TEST_CASE("deep atomic compare-and-swap") CHECK(101 == res.error_code()); CHECK("Compare failed" == res.error_message()); - // succes with the correct index res = etcd.modify_if("/test/key1", "44", index).get(); REQUIRE(res.is_ok()); @@ -200,21 +190,8 @@ TEST_CASE("deep atomic compare-and-swap") CHECK(!res.is_ok()); CHECK(101 == res.error_code()); CHECK("Compare failed" == res.error_message()); - } - -//skip this test case -/* -TEST_CASE("create a directory") -{ - etcd::Client etcd("http://127.0.0.1:4001"); - etcd::Response resp = etcd.mkdir("/test/new_dir").get(); - CHECK("set" == resp.action()); - CHECK(resp.value().is_dir()); -} -*/ - TEST_CASE("list a directory") { etcd::Client etcd("http://127.0.0.1:2379"); @@ -249,7 +226,7 @@ TEST_CASE("delete a directory") { etcd::Client etcd("http://127.0.0.1:2379"); - //CHECK(108 == etcd.rmdir("/test/new_dir").get().error_code()); // Directory not empty + CHECK(100 == etcd.rmdir("/test/new_dir").get().error_code()); // key not found etcd::Response resp = etcd.ls("/test/new_dir").get(); diff --git a/tst/LockTest.cpp b/tst/LockTest.cpp index 8cb5950..5611c27 100644 --- a/tst/LockTest.cpp +++ b/tst/LockTest.cpp @@ -1,5 +1,7 @@ -#include +#define CATCH_CONFIG_MAIN #include + +#include #include #include @@ -23,7 +25,6 @@ TEST_CASE("lock and unlock") REQUIRE(0 == resp2.error_code()); } - TEST_CASE("double lock will fail") { etcd::Client etcd("http://127.0.0.1:2379"); diff --git a/tst/WatcherTest.cpp b/tst/WatcherTest.cpp index 1551573..7cf3609 100644 --- a/tst/WatcherTest.cpp +++ b/tst/WatcherTest.cpp @@ -1,3 +1,4 @@ +#define CATCH_CONFIG_MAIN #include #include "etcd/Watcher.hpp" @@ -10,8 +11,9 @@ void printResponse(etcd::Response const & resp) { ++watcher_called; std::cout << "print response called" << std::endl; - if (resp.error_code()) + if (resp.error_code()) { std::cout << resp.error_code() << ": " << resp.error_message() << std::endl; + } else { std::cout << resp.action() << " " << resp.value().as_string() << std::endl; @@ -46,7 +48,6 @@ TEST_CASE("create watcher with cancel") TEST_CASE("create watcher") { - etcd::SyncClient etcd(etcd_uri); etcd.rmdir("/test", true); @@ -74,17 +75,13 @@ TEST_CASE("create watcher") // sleep(1); // REQUIRE(res.is_done()); -// try -// { +// try { // res.wait(); // } -// catch(pplx::task_canceled const & ex) -// { +// catch(pplx::task_canceled const & ex) { // std::cout << "pplx::task_canceled: " << ex.what() << "\n"; // } -// catch(std::exception const & ex) -// { +// catch(std::exception const & ex) { // std::cout << "std::exception: " << ex.what() << "\n"; // } // } -