Refactored and cleaned implementation for rm()

Unrelated tests are commented out firsts
temporary method, such as getV3, are done to be able to do the original UT replication.
This commit is contained in:
lampayan 2016-06-08 11:11:50 +02:00
parent 98e2b57ed4
commit 62d4984e71
12 changed files with 429 additions and 364 deletions

View File

@ -0,0 +1,26 @@
/*
* AsyncDeleteResponse.h
*
* Created on: Jun 7, 2016
* Author: ubuntu
*/
#ifndef SRC_ASYNCDELETERESPONSE_H_
#define SRC_ASYNCDELETERESPONSE_H_
#include "etcd/BaseResponse.h"
namespace etcd {
class AsyncDeleteResponse : public etcd::BaseResponse {
public:
AsyncDeleteResponse();
virtual ~AsyncDeleteResponse();
void fillUpV2ResponseValues(etcdserverpb::RangeResponse);
etcdserverpb::DeleteRangeResponse deleteResponse;
std::unique_ptr<grpc::ClientAsyncResponseReader<etcdserverpb::DeleteRangeResponse>> rpcInstance;
};
}
#endif /* SRC_ASYNCDELETERESPONSE_H_ */

26
etcd/BaseResponse.h Normal file
View File

@ -0,0 +1,26 @@
/*
* BaseResponse.h
*
* Created on: Jun 7, 2016
* Author: ubuntu
*/
#ifndef SRC_BASERESPONSE_H_
#define SRC_BASERESPONSE_H_
#include "etcd/Response.hpp"
#include "proto/rpc.grpc.pb.h"
namespace etcd {
class BaseResponse : public etcd::Response {
public:
//TODO: turn into a abstract class
BaseResponse();
virtual ~BaseResponse();
grpc::Status status;
grpc::ClientContext context;
grpc::CompletionQueue cq_;
};
}
#endif /* SRC_BASERESPONSE_H_ */

View File

@ -8,6 +8,8 @@
#include <grpc++/grpc++.h>
#include "proto/rpc.grpc.pb.h"
#include "etcd/DeleteRpcResponse.h"
#include "etcd/AsyncDeleteResponse.h"
using grpc::Channel;
using grpc::ClientAsyncResponseReader;
@ -159,7 +161,10 @@ namespace etcd
std::unique_ptr<Watch::Stub> watchServiceStub;
pplx::task<etcd::Response> send_put(const std::string& key, const std::string& value);
pplx::task<etcd::Response> send_get(std::string const & key);
};
private:
void getEntryForPreviousValue(const std::string& entryKey, etcd::AsyncDeleteResponse* drp);
};
class AsyncPutResponse
{

View File

@ -5,24 +5,26 @@
* Author: ubuntu
*/
#ifndef SRC_DELETERPCRESPONSE_H_
#define SRC_DELETERPCRESPONSE_H_
#include "etcd/Response.hpp"
#include "proto/rpc.grpc.pb.h"
namespace etcd {
class DeleteRpcResponse : public etcd::Response, public etcd::Value {
public:
DeleteRpcResponse();
virtual ~DeleteRpcResponse();
void fillUpV2ResponseValues(etcdserverpb::RangeResponse);
etcdserverpb::DeleteRangeResponse deleteResponse;
grpc::Status status;
grpc::ClientContext context;
grpc::CompletionQueue cq_;
std::unique_ptr<grpc::ClientAsyncResponseReader<etcdserverpb::DeleteRangeResponse>> rpcInstance;
};
}
#endif /* SRC_DELETERPCRESPONSE_H_ */
//#ifndef SRC_DELETERPCRESPONSE_H_
//#define SRC_DELETERPCRESPONSE_H_
//
//#include "etcd/Response.hpp"
//#include "proto/rpc.grpc.pb.h"
//
//namespace etcd {
//class DeleteRpcResponse : public etcd::Response, public etcd::Value {
//public:
// DeleteRpcResponse();
// virtual ~DeleteRpcResponse();
// void fillUpV2ResponseValues(etcdserverpb::RangeResponse);
//
// etcdserverpb::DeleteRangeResponse deleteResponse;
//
// grpc::Status status;
// grpc::ClientContext context;
// grpc::CompletionQueue cq_;
//
// std::unique_ptr<grpc::ClientAsyncResponseReader<etcdserverpb::DeleteRangeResponse>> rpcInstance;
//};
//}
//#endif /* SRC_DELETERPCRESPONSE_H_ */

View File

@ -20,9 +20,7 @@ namespace etcd
public:
static pplx::task<Response> create(pplx::task<web::http::http_response> response_task);
//parang mas magandang ilagay ito sa baseclass imbis na here ooorrr
//talagang response v2 lang talaga dito
template<typename T>static pplx::task<etcd::Response> create(T call)
template<typename T>static pplx::task<etcd::Response> createV2Response(T call)
{
return pplx::task<etcd::Response>([call]()
{
@ -39,7 +37,7 @@ namespace etcd
if(call->status.ok())
{
// auto v3resp = call->ParseResponse();
resp = *call;// stripping off instead of creating a new response class
resp = *call;// stripping off instead of creating a new response class object
}
else
{

View File

@ -41,7 +41,9 @@ namespace etcd
protected:
friend class Response;
friend class BaseResponse; //deliberately done since Value class will be removed during full V3
friend class DeleteRpcResponse;
friend class AsyncDeleteResponse;
Value();
Value(web::json::value const & json_value);
std::string _key;

View File

@ -0,0 +1,21 @@
/*
* AsyncDeleteResponse.cpp
*
* Created on: Jun 7, 2016
* Author: ubuntu
*/
#include "etcd/AsyncDeleteResponse.h"
etcd::AsyncDeleteResponse::AsyncDeleteResponse() {
// TODO Auto-generated constructor stub
}
etcd::AsyncDeleteResponse::~AsyncDeleteResponse() {
// TODO Auto-generated destructor stub
}
void etcd::AsyncDeleteResponse::fillUpV2ResponseValues(etcdserverpb::RangeResponse getResponse) {
_prev_value.value = getResponse.kvs().Get(0).value();
_action = "delete";
}

17
src/BaseResponse.cpp Normal file
View File

@ -0,0 +1,17 @@
/*
* BaseResponse.cpp
*
* Created on: Jun 7, 2016
* Author: ubuntu
*/
#include "etcd/BaseResponse.h"
etcd::BaseResponse::BaseResponse() {
// TODO Auto-generated constructor stub
}
etcd::BaseResponse::~BaseResponse() {
// TODO Auto-generated destructor stub
}

View File

@ -1,4 +1,4 @@
add_library(etcd-cpp-api SHARED ../proto/kv.pb.cc ../proto/auth.pb.cc ../proto/rpc.pb.cc ../proto/rpc.grpc.pb.cc Client.cpp Response.cpp Value.cpp json_constants.cpp DeleteRpcResponse.cpp)
add_library(etcd-cpp-api SHARED ../proto/kv.pb.cc ../proto/auth.pb.cc ../proto/rpc.pb.cc ../proto/rpc.grpc.pb.cc Client.cpp Response.cpp Value.cpp json_constants.cpp BaseResponse.cpp AsyncDeleteResponse.cpp)
set_property(TARGET etcd-cpp-api PROPERTY CXX_STANDARD 11)
target_link_libraries(etcd-cpp-api ${CPPREST_LIB} boost_system ssl crypto protobuf grpc++)

View File

@ -2,6 +2,7 @@
#include <iostream>
#include "etcd/DeleteRpcResponse.h"
#include "etcd/AsyncDeleteResponse.h"
etcd::Client::Client(std::string const & address)
: client(address)
@ -45,9 +46,9 @@ pplx::task<etcd::Response> etcd::Client::set(std::string const & key, std::strin
return send_put(key,value);
}
//TODO: a temporary set, until set version 3 is implemented
void etcd::Client::setv3(std::string const &key, std::string const &value)
{
std::cout << "FBDL setv3" << std::endl;
etcdserverpb::PutRequest putRequest;
putRequest.set_key(key);
putRequest.set_value(value);
@ -93,31 +94,25 @@ pplx::task<etcd::Response> etcd::Client::modify_if(std::string const & key, std:
return send_put_request(uri, "value", value);
}
pplx::task<etcd::Response> etcd::Client::removeEntry(std::string const & entryKey) {
etcd::DeleteRpcResponse *drp = new etcd::DeleteRpcResponse();
//get muna
std::cout<<"blocking call for get rpc first " << entryKey << std::endl;
void etcd::Client::getEntryForPreviousValue(const std::string& entryKey, etcd::AsyncDeleteResponse* drp)
{
etcdserverpb::RangeRequest rangeRequest;
rangeRequest.set_key(entryKey);
etcdserverpb::RangeResponse rangeResponse;
grpc::ClientContext context;
grpc::Status status = stub_->Range(&context, rangeRequest, &rangeResponse);
if(status.ok()) {
if (status.ok()) {
std::cout << "get OK" << std::endl;
drp->fillUpV2ResponseValues(rangeResponse);
}
else {
} else {
std::cout << "get NOK" << std::endl;
}
}
pplx::task<etcd::Response> etcd::Client::removeEntry(std::string const & entryKey) {
//then delete
std::cout << "removing etcd v3 entry naman with template na" << std::endl;
etcd::AsyncDeleteResponse *drp = new etcd::AsyncDeleteResponse();
getEntryForPreviousValue(entryKey, drp); //TODO: failure case scenario handling
etcdserverpb::DeleteRangeRequest deleteRangeRequest;
deleteRangeRequest.set_key(entryKey);
@ -125,32 +120,7 @@ pplx::task<etcd::Response> etcd::Client::removeEntry(std::string const & entryKe
drp->rpcInstance = stub_->AsyncDeleteRange(&drp->context, deleteRangeRequest, &drp->cq_);
drp->rpcInstance->Finish(&drp->deleteResponse, &drp->status, (void*)drp);
return Response::create(drp);
// return pplx::task<etcd::Response>([drp]()
// {
// std::cout << "doing delete v3 entry task" << std::endl;
// void* got_tag;
// bool ok = false;
// etcd::Response resp;
//
// drp->completionQueue.Next(&got_tag, &ok);
// GPR_ASSERT(got_tag == (void*)drp);
// GPR_ASSERT(ok);
//
// etcd::DeleteRpcResponse* deleteResponse = static_cast<etcd::DeleteRpcResponse*>(got_tag);
//
// if (deleteResponse->status.ok()){
// std::cout << "doing delete v3 entry task OK" << std::endl;
// resp = *drp; //simply stripping off the response part
// }
// else
// std::cout << "doing delete v3 entry task NOK" << std::endl;
// delete deleteResponse;
// std::cout << "delete done, returning" << std::endl;
// return resp;
// }
// );
return Response::createV2Response(drp);
}
@ -173,7 +143,7 @@ void etcd::Client::getv3(std::string const & key) {
std::cout << "kvs 0 value: " << rangeResponse.kvs(0).value() << std::endl;
std::cout << "kvs.Get 0 value: " << rangeResponse.kvs().Get(0).value() << std::endl;
DeleteRpcResponse drp;
AsyncDeleteResponse drp;
drp.fillUpV2ResponseValues(rangeResponse);
}
else {

View File

@ -5,35 +5,34 @@
* Author: ubuntu
*/
#include "etcd/DeleteRpcResponse.h"
#include <iostream>
etcd::DeleteRpcResponse::DeleteRpcResponse() {
// TODO Auto-generated constructor stub
}
etcd::DeleteRpcResponse::~DeleteRpcResponse() {
// TODO Auto-generated destructor stub
}
//prototype in handling the response object
void etcd::DeleteRpcResponse::fillUpV2ResponseValues(etcdserverpb::RangeResponse getResponse) {
std::cout << "inside fillup attempting fillupv2 response values" << std::endl;
std::cout << "setting the value of: " << getResponse.kvs().Get(0).value() << std::endl;
_prev_value.value = getResponse.kvs().Get(0).value();
_action = "delete";
// //the experiments done on how to fill up the field of this object.
// //access the fields na protected sa Value
// this->Value::value = "yeah";
// std::cout << "pre contents: " << this->_value.as_string() << std::endl;
//#include "etcd/DeleteRpcResponse.h"
//#include <iostream>
//
// //or create an instance here and return it filled up
// DeleteRpcResponse r;
// r.Value::value = "yo!";
// this->_value = r; //strip off value part
//etcd::DeleteRpcResponse::DeleteRpcResponse() {
// // TODO Auto-generated constructor stub
//
// std::cout << "contents: " << this->_value.as_string() << std::endl;
}
//}
//
//etcd::DeleteRpcResponse::~DeleteRpcResponse() {
// // TODO Auto-generated destructor stub
//}
//
//void etcd::DeleteRpcResponse::fillUpV2ResponseValues(etcdserverpb::RangeResponse getResponse) {
// std::cout << "inside fillup attempting fillupv2 response values" << std::endl;
//
// std::cout << "setting the value of: " << getResponse.kvs().Get(0).value() << std::endl;
// _prev_value.value = getResponse.kvs().Get(0).value();
// _action = "delete";
//
//// //the experiments done on how to fill up the field of this object.
//// //access the fields na protected sa Value
//// this->Value::value = "yeah";
//// std::cout << "pre contents: " << this->_value.as_string() << std::endl;
////
//// //or create an instance here and return it filled up
//// DeleteRpcResponse r;
//// r.Value::value = "yo!";
//// this->_value = r; //strip off value part
////
//// std::cout << "contents: " << this->_value.as_string() << std::endl;
//}

View File

@ -3,287 +3,286 @@
#include "etcd/Client.hpp"
TEST_CASE("setup")
{
etcd::Client etcd("http://127.0.0.1:4001");
etcd.rmdir("/test", true).wait();
}
TEST_CASE("add a new key")
{
etcd::Client etcd("http://127.0.0.1:4001");
etcd::Response resp = etcd.add("/test/key1", "42").get();
REQUIRE(0 == resp.error_code());
CHECK("create" == resp.action());
etcd::Value const & val = resp.value();
CHECK("42" == val.as_string());
CHECK("/test/key1" == val.key());
CHECK(!val.is_dir());
CHECK(0 < val.created_index());
CHECK(0 < val.modified_index());
CHECK(0 < resp.index()); // X-Etcd-Index header value
CHECK(105 == etcd.add("/test/key1", "43").get().error_code()); // Key already exists
CHECK(105 == etcd.add("/test/key1", "42").get().error_code()); // Key already exists
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:4001");
etcd::Response resp = etcd.get("/test/key1").get();
CHECK("get" == resp.action());
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:4001");
CHECK("42" == etcd.get("/test/key1").get().value().as_string());
std::cout << "get error code kahit success: " << etcd.get("/test/key1").get().error_code() << std::endl;
CHECK(100 == etcd.get("/test/key2").get().error_code()); // Key not found
}
TEST_CASE("modify a key")
{
etcd::Client etcd("http://127.0.0.1:4001");
etcd::Response resp = etcd.modify("/test/key1", "43").get();
REQUIRE(0 == resp.error_code()); // overwrite
CHECK("update" == resp.action());
CHECK(100 == etcd.modify("/test/key2", "43").get().error_code()); // Key not found
CHECK("43" == etcd.modify("/test/key1", "42").get().prev_value().as_string());
}
//TEST_CASE("set a key")
//TEST_CASE("setup")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// etcd::Response resp = etcd.set("/test/key1", "43").get();
// etcd.rmdir("/test", true).wait();
//}
//
//TEST_CASE("add a new key")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// etcd::Response resp = etcd.add("/test/key1", "42").get();
// REQUIRE(0 == resp.error_code());
// CHECK("create" == resp.action());
// etcd::Value const & val = resp.value();
// CHECK("42" == val.as_string());
// CHECK("/test/key1" == val.key());
// CHECK(!val.is_dir());
// CHECK(0 < val.created_index());
// CHECK(0 < val.modified_index());
// CHECK(0 < resp.index()); // X-Etcd-Index header value
// CHECK(105 == etcd.add("/test/key1", "43").get().error_code()); // Key already exists
// CHECK(105 == etcd.add("/test/key1", "42").get().error_code()); // Key already exists
// 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:4001");
// etcd::Response resp = etcd.get("/test/key1").get();
// CHECK("get" == resp.action());
// 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:4001");
// CHECK("42" == etcd.get("/test/key1").get().value().as_string());
// std::cout << "get error code kahit success: " << etcd.get("/test/key1").get().error_code() << std::endl;
// CHECK(100 == etcd.get("/test/key2").get().error_code()); // Key not found
//}
//
//TEST_CASE("modify a key")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// etcd::Response resp = etcd.modify("/test/key1", "43").get();
// REQUIRE(0 == resp.error_code()); // overwrite
// CHECK("set" == resp.action());
// CHECK(0 == etcd.set("/test/key2", "43").get().error_code()); // create new
// CHECK("43" == etcd.set("/test/key2", "44").get().prev_value().as_string());
// CHECK("" == etcd.set("/test/key3", "44").get().prev_value().as_string());
// CHECK(102 == etcd.set("/test", "42").get().error_code()); // Not a file
// CHECK("update" == resp.action());
// CHECK(100 == etcd.modify("/test/key2", "43").get().error_code()); // Key not found
// CHECK("43" == etcd.modify("/test/key1", "42").get().prev_value().as_string());
//}
//
//FBDL rm naman
//TEST_CASE("delete a value")
//{
// std::cout << "FBDL do a delete via rm only" <<std::endl;
// etcd::Client etcd("http://127.0.0.1:4001");
// CHECK(3 == etcd.ls("/test").get().keys().size());
//
// std::cout << "FBDL invoking rm in test" <<std::endl;
// etcd::Response resp = etcd.rm("/test/key1").get();
// CHECK("43" == resp.prev_value().as_string());
// CHECK("delete" == resp.action());
// CHECK(2 == etcd.ls("/test").get().keys().size());
//}
////TEST_CASE("set a key")
////{
//// etcd::Client etcd("http://127.0.0.1:4001");
//// etcd::Response resp = etcd.set("/test/key1", "43").get();
//// REQUIRE(0 == resp.error_code()); // overwrite
//// CHECK("set" == resp.action());
//// CHECK(0 == etcd.set("/test/key2", "43").get().error_code()); // create new
//// CHECK("43" == etcd.set("/test/key2", "44").get().prev_value().as_string());
//// CHECK("" == etcd.set("/test/key3", "44").get().prev_value().as_string());
//// CHECK(102 == etcd.set("/test", "42").get().error_code()); // Not a file
////}
////
////FBDL rm naman
////TEST_CASE("delete a value")
////{
//// std::cout << "FBDL do a delete via rm only" <<std::endl;
//// etcd::Client etcd("http://127.0.0.1:4001");
//// CHECK(3 == etcd.ls("/test").get().keys().size());
////
//// std::cout << "FBDL invoking rm in test" <<std::endl;
//// etcd::Response resp = etcd.rm("/test/key1").get();
//// CHECK("43" == resp.prev_value().as_string());
//// CHECK("delete" == resp.action());
//// CHECK(2 == etcd.ls("/test").get().keys().size());
////}
TEST_CASE("delete a value V3")
TEST_CASE("delete a value V3 representation")
{
std::cout << "FBDL do a delete via rm only V3" <<std::endl;
etcd::Client etcd("http://127.0.0.1:4001");
etcd.setv3("test/key1", "42"); //temporary get
etcd.setv3("test/key1", "42");
etcd::Response resp = etcd.rm("test/key1").get();
CHECK("42" == resp.prev_value().as_string());
CHECK("delete" == resp.action());
}
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:4001");
CHECK(0 == etcd.ls("/test/new_dir").get().keys().size());
etcd.set("/test/new_dir/key1", "value1").wait();
etcd.set("/test/new_dir/key2", "value2").wait();
etcd.mkdir("/test/new_dir/sub_dir").wait();
etcd::Response resp = etcd.ls("/test/new_dir").get();
CHECK("get" == resp.action());
REQUIRE(3 == resp.keys().size());
CHECK("key1" == resp.key(0));
CHECK("key2" == resp.key(1));
CHECK("sub_dir" == resp.key(2));
CHECK("value1" == resp.value(0).as_string());
CHECK("value2" == resp.value(1).as_string());
CHECK(resp.values()[2].is_dir());
CHECK(0 == etcd.ls("/test/new_dir/key1").get().error_code());
}
TEST_CASE("delete a directory")
{
etcd::Client etcd("http://127.0.0.1:4001");
CHECK(108 == etcd.rmdir("/test/new_dir").get().error_code()); // Directory not empty
CHECK(0 == etcd.rmdir("/test/new_dir", true).get().error_code());
}
TEST_CASE("wait for a value change")
{
etcd::Client etcd("http://127.0.0.1:4001");
etcd.set("/test/key1", "42").wait();
pplx::task<etcd::Response> res = etcd.watch("/test/key1");
CHECK(!res.is_done());
sleep(1);
CHECK(!res.is_done());
etcd.set("/test/key1", "43").get();
sleep(1);
REQUIRE(res.is_done());
REQUIRE("set" == res.get().action());
CHECK("43" == res.get().value().as_string());
}
//FBDL: first watch
//TEST_CASE("FBDL wait for a value change")
//TEST_CASE("create a directory")
//{
// std::cout << "FBDL wait for a value change" << std::endl;
// etcd::Client etcd("http://127.0.0.1:4001");
//// etcd.set("/test/key1", "42").wait();
// etcd.setv3("test/key1", "42");
//
//// pplx::task<etcd::Response> res = etcd.watch("/test/key1");
//// CHECK(!res.is_done());
//// sleep(1);
//// CHECK(!res.is_done());
//// CHECK("42" == etcd.get("/test/key1").get().value().as_string());
////
//// etcd.set("/test/key1", "43").get();
//// sleep(1);
//// REQUIRE(res.is_done());
//// REQUIRE("set" == res.get().action());
//// CHECK("43" == res.get().value().as_string());
//// CHECK("43" == etcd.get("/test/key1").get().value().as_string());
// 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:4001");
// CHECK(0 == etcd.ls("/test/new_dir").get().keys().size());
//
// etcd.set("/test/new_dir/key1", "value1").wait();
// etcd.set("/test/new_dir/key2", "value2").wait();
// etcd.mkdir("/test/new_dir/sub_dir").wait();
//
// etcd::Response resp = etcd.ls("/test/new_dir").get();
// CHECK("get" == resp.action());
// REQUIRE(3 == resp.keys().size());
// CHECK("key1" == resp.key(0));
// CHECK("key2" == resp.key(1));
// CHECK("sub_dir" == resp.key(2));
// CHECK("value1" == resp.value(0).as_string());
// CHECK("value2" == resp.value(1).as_string());
// CHECK(resp.values()[2].is_dir());
//
// CHECK(0 == etcd.ls("/test/new_dir/key1").get().error_code());
//}
//
//TEST_CASE("delete a directory")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// CHECK(108 == etcd.rmdir("/test/new_dir").get().error_code()); // Directory not empty
// CHECK(0 == etcd.rmdir("/test/new_dir", true).get().error_code());
//}
//
//TEST_CASE("wait for a value change")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// etcd.set("/test/key1", "42").wait();
//
// pplx::task<etcd::Response> res = etcd.watch("/test/key1");
// CHECK(!res.is_done());
// sleep(1);
// CHECK(!res.is_done());
//
// etcd.set("/test/key1", "43").get();
// sleep(1);
// REQUIRE(res.is_done());
// REQUIRE("set" == res.get().action());
// CHECK("43" == res.get().value().as_string());
//}
//
////FBDL: first watch
////TEST_CASE("FBDL wait for a value change")
////{
//// std::cout << "FBDL wait for a value change" << std::endl;
//// etcd::Client etcd("http://127.0.0.1:4001");
////// etcd.set("/test/key1", "42").wait();
//// etcd.setv3("test/key1", "42");
////
////// pplx::task<etcd::Response> res = etcd.watch("/test/key1");
////// CHECK(!res.is_done());
////// sleep(1);
////// CHECK(!res.is_done());
////// CHECK("42" == etcd.get("/test/key1").get().value().as_string());
//////
////// etcd.set("/test/key1", "43").get();
////// sleep(1);
////// REQUIRE(res.is_done());
////// REQUIRE("set" == res.get().action());
////// CHECK("43" == res.get().value().as_string());
////// CHECK("43" == etcd.get("/test/key1").get().value().as_string());
////}
//
//TEST_CASE("wait for a directory change")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
//
// pplx::task<etcd::Response> res = etcd.watch("/test", true);
// CHECK(!res.is_done());
// sleep(1);
// CHECK(!res.is_done());
//
// etcd.add("/test/key4", "44").wait();
// sleep(1);
// REQUIRE(res.is_done());
// CHECK("create" == res.get().action());
// CHECK("44" == res.get().value().as_string());
//
// pplx::task<etcd::Response> res2 = etcd.watch("/test", true);
// CHECK(!res2.is_done());
// sleep(1);
// CHECK(!res2.is_done());
//
// etcd.set("/test/key4", "45").wait();
// REQUIRE(res2.is_done());
// CHECK("set" == res2.get().action());
// CHECK("45" == res2.get().value().as_string());
//}
//
//TEST_CASE("watch changes in the past")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
//
// int index = etcd.set("/test/key1", "42").get().index();
//
// 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());
//}
//
//TEST_CASE("atomic compare-and-swap")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// etcd.set("/test/key1", "42").wait();
//
// // modify success
// etcd::Response res = etcd.modify_if("/test/key1", "43", "42").get();
// int index = res.index();
// REQUIRE(res.is_ok());
// CHECK("compareAndSwap" == res.action());
// CHECK("43" == res.value().as_string());
//
// // modify fails the second time
// res = etcd.modify_if("/test/key1", "44", "42").get();
// CHECK(!res.is_ok());
// 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());
// CHECK("compareAndSwap" == res.action());
// CHECK("44" == res.value().as_string());
//
// // index changes so second modify fails
// res = etcd.modify_if("/test/key1", "45", index).get();
// CHECK(!res.is_ok());
// CHECK(101 == res.error_code());
// CHECK("Compare failed" == res.error_message());
//}
//
//TEST_CASE("atomic compare-and-delete based on prevValue")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// etcd.set("/test/key1", "42").wait();
//
// etcd::Response res = etcd.rm_if("/test/key1", "43").get();
// CHECK(!res.is_ok());
// CHECK(101 == res.error_code());
// CHECK("Compare failed" == res.error_message());
//
// res = etcd.rm_if("/test/key1", "42").get();
// REQUIRE(res.is_ok());
// CHECK("compareAndDelete" == res.action());
// CHECK("42" == res.prev_value().as_string());
//}
//
//TEST_CASE("atomic compare-and-delete based on prevIndex")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// int index = etcd.set("/test/key1", "42").get().index();
//
// etcd::Response res = etcd.rm_if("/test/key1", index - 1).get();
// CHECK(!res.is_ok());
// CHECK(101 == res.error_code());
// CHECK("Compare failed" == res.error_message());
//
// res = etcd.rm_if("/test/key1", index).get();
// REQUIRE(res.is_ok());
// CHECK("compareAndDelete" == res.action());
// CHECK("42" == res.prev_value().as_string());
//}
//
//TEST_CASE("cleanup")
//{
// etcd::Client etcd("http://127.0.0.1:4001");
// REQUIRE(0 == etcd.rmdir("/test", true).get().error_code());
//}
TEST_CASE("wait for a directory change")
{
etcd::Client etcd("http://127.0.0.1:4001");
pplx::task<etcd::Response> res = etcd.watch("/test", true);
CHECK(!res.is_done());
sleep(1);
CHECK(!res.is_done());
etcd.add("/test/key4", "44").wait();
sleep(1);
REQUIRE(res.is_done());
CHECK("create" == res.get().action());
CHECK("44" == res.get().value().as_string());
pplx::task<etcd::Response> res2 = etcd.watch("/test", true);
CHECK(!res2.is_done());
sleep(1);
CHECK(!res2.is_done());
etcd.set("/test/key4", "45").wait();
REQUIRE(res2.is_done());
CHECK("set" == res2.get().action());
CHECK("45" == res2.get().value().as_string());
}
TEST_CASE("watch changes in the past")
{
etcd::Client etcd("http://127.0.0.1:4001");
int index = etcd.set("/test/key1", "42").get().index();
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());
}
TEST_CASE("atomic compare-and-swap")
{
etcd::Client etcd("http://127.0.0.1:4001");
etcd.set("/test/key1", "42").wait();
// modify success
etcd::Response res = etcd.modify_if("/test/key1", "43", "42").get();
int index = res.index();
REQUIRE(res.is_ok());
CHECK("compareAndSwap" == res.action());
CHECK("43" == res.value().as_string());
// modify fails the second time
res = etcd.modify_if("/test/key1", "44", "42").get();
CHECK(!res.is_ok());
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());
CHECK("compareAndSwap" == res.action());
CHECK("44" == res.value().as_string());
// index changes so second modify fails
res = etcd.modify_if("/test/key1", "45", index).get();
CHECK(!res.is_ok());
CHECK(101 == res.error_code());
CHECK("Compare failed" == res.error_message());
}
TEST_CASE("atomic compare-and-delete based on prevValue")
{
etcd::Client etcd("http://127.0.0.1:4001");
etcd.set("/test/key1", "42").wait();
etcd::Response res = etcd.rm_if("/test/key1", "43").get();
CHECK(!res.is_ok());
CHECK(101 == res.error_code());
CHECK("Compare failed" == res.error_message());
res = etcd.rm_if("/test/key1", "42").get();
REQUIRE(res.is_ok());
CHECK("compareAndDelete" == res.action());
CHECK("42" == res.prev_value().as_string());
}
TEST_CASE("atomic compare-and-delete based on prevIndex")
{
etcd::Client etcd("http://127.0.0.1:4001");
int index = etcd.set("/test/key1", "42").get().index();
etcd::Response res = etcd.rm_if("/test/key1", index - 1).get();
CHECK(!res.is_ok());
CHECK(101 == res.error_code());
CHECK("Compare failed" == res.error_message());
res = etcd.rm_if("/test/key1", index).get();
REQUIRE(res.is_ok());
CHECK("compareAndDelete" == res.action());
CHECK("42" == res.prev_value().as_string());
}
TEST_CASE("cleanup")
{
etcd::Client etcd("http://127.0.0.1:4001");
REQUIRE(0 == etcd.rmdir("/test", true).get().error_code());
}