Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

285 lines (249 sloc) 8.02 kb
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2012 Couchbase, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "config.h"
#include <gtest/gtest.h>
#include <libcouchbase/couchbase.h>
#include <map>
#include "server.h"
#include "mock-unit-test.h"
#include "testutil.h"
class GetUnitTest : public MockUnitTest
{
protected:
static void SetUpTestCase() {
MockUnitTest::SetUpTestCase();
}
};
extern "C" {
static void testGetMissGetCallback(lcb_t, const void *cookie,
lcb_error_t error,
const lcb_get_resp_t *resp)
{
int *counter = (int *)cookie;
EXPECT_EQ(LCB_KEY_ENOENT, error);
ASSERT_NE((const lcb_get_resp_t *)NULL, resp);
EXPECT_EQ(0, resp->version);
std::string val((const char *)resp->v.v0.key, resp->v.v0.nkey);
EXPECT_TRUE(val == "testGetMiss1" || val == "testGetMiss2");
++(*counter);
}
}
/**
* @test
* Get Miss
*
* @pre
* Request two non-existent keys
*
* @post
* Responses for both keys are received with error code
* @c KEY_ENOENT; response structure is not NULL, and the keys match their
* expected value
*
* @todo (maybe check the values too?)
*/
TEST_F(GetUnitTest, testGetMiss)
{
lcb_t instance;
createConnection(instance);
(void)lcb_set_get_callback(instance, testGetMissGetCallback);
int numcallbacks = 0;
removeKey(instance, "testGetMiss1");
removeKey(instance, "testGetMiss2");
lcb_get_cmd_t cmd1("testGetMiss1");
lcb_get_cmd_t cmd2("testGetMiss2");
lcb_get_cmd_t *cmds[] = { &cmd1, &cmd2 };
EXPECT_EQ(LCB_SUCCESS, lcb_get(instance, &numcallbacks, 2, cmds));
lcb_wait(instance);
EXPECT_EQ(2, numcallbacks);
}
extern "C" {
static void testGetHitGetCallback(lcb_t, const void *cookie,
lcb_error_t error,
const lcb_get_resp_t *resp)
{
int *counter = (int *)cookie;
EXPECT_EQ(LCB_SUCCESS, error);
ASSERT_NE((const lcb_get_resp_t *)NULL, resp);
EXPECT_EQ(0, resp->version);
++(*counter);
}
}
/**
* @test
* Get Hit
*
* @pre
* Store two keys, and retrieve them
*
* @post
* Both keys exist, and their return code is successul
*/
TEST_F(GetUnitTest, testGetHit)
{
lcb_t instance;
createConnection(instance);
(void)lcb_set_get_callback(instance, testGetHitGetCallback);
int numcallbacks = 0;
storeKey(instance, "testGetKey1", "foo");
storeKey(instance, "testGetKey2", "foo");
lcb_get_cmd_t cmd1("testGetKey1");
lcb_get_cmd_t cmd2("testGetKey2");
lcb_get_cmd_t *cmds[] = { &cmd1, &cmd2 };
EXPECT_EQ(LCB_SUCCESS, lcb_get(instance, &numcallbacks, 2, cmds));
lcb_wait(instance);
EXPECT_EQ(2, numcallbacks);
}
extern "C" {
static void testTouchMissCallback(lcb_t, const void *cookie,
lcb_error_t error,
const lcb_touch_resp_t *resp)
{
int *counter = (int *)cookie;
EXPECT_EQ(LCB_KEY_ENOENT, error);
ASSERT_NE((const lcb_touch_resp_t *)NULL, resp);
EXPECT_EQ(0, resp->version);
++(*counter);
}
}
/**
* @test Touch (Miss)
* @pre Schedule a touch for a non existent key with an expiry @c 666
* @post Touch fails with @c KEY_ENOENT
*/
TEST_F(GetUnitTest, testTouchMiss)
{
std::string key("testTouchMissKey");
lcb_t instance;
createConnection(instance);
(void)lcb_set_touch_callback(instance, testTouchMissCallback);
removeKey(instance, key);
int numcallbacks = 0;
lcb_touch_cmd_t cmd(key.data(), key.length(), 666);
lcb_touch_cmd_t *cmds[] = { &cmd };
EXPECT_EQ(LCB_SUCCESS, lcb_touch(instance, &numcallbacks, 1, cmds));
lcb_wait(instance);
EXPECT_EQ(1, numcallbacks);
}
extern "C" {
static void testTouchHitCallback(lcb_t, const void *cookie,
lcb_error_t error,
const lcb_touch_resp_t *resp)
{
int *counter = (int *)cookie;
EXPECT_EQ(LCB_SUCCESS, error);
ASSERT_NE((const lcb_touch_resp_t *)NULL, resp);
EXPECT_EQ(0, resp->version);
++(*counter);
}
}
/**
* @test Touch (Hit)
* @pre Store a key, and schedule a touch operation with an expiry of @c 666
* @post Touch succeeds.
*/
TEST_F(GetUnitTest, testTouchHit)
{
std::string key("testTouchHitKey");
lcb_t instance;
createConnection(instance);
(void)lcb_set_touch_callback(instance, testTouchHitCallback);
storeKey(instance, key, "foo");
int numcallbacks = 0;
lcb_touch_cmd_t cmd(key.data(), key.length(), 666);
lcb_touch_cmd_t *cmds[] = { &cmd };
EXPECT_EQ(LCB_SUCCESS, lcb_touch(instance, &numcallbacks, 1, cmds));
lcb_wait(instance);
EXPECT_EQ(1, numcallbacks);
}
extern "C" {
static void testMixedMultiGetCallback(lcb_t, const void *cookie,
lcb_error_t error,
const lcb_get_resp_t *resp)
{
using namespace std;
map<string, Item> *kmap = (map<string, Item> *)cookie;
Item itm;
itm.assign(resp, error);
(*kmap)[itm.key] = itm;
}
}
/**
* Adopted from smoke-test.c:test_get2
*
* @test Multi Get (Interleaved)
*
* @pre
* Create two maps of 26 key-value pairs, one called @c kexisting and one
* called @c kmissing. Store the @c kexisting map but not the @c kmissing one.
*
* Create a list of GET commands interleaving keys from @c kmissing and
* @c kexisting. Schedule the operation
*
* @post
* Returned result set has exactly 52 items. All the keys from @c kmissing
* have @c KEY_ENOENT from their result code, and all keys from @c kexisting
* contain the appropriate values.
*/
TEST_F(GetUnitTest, testMixedMultiGet)
{
using namespace std;
lcb_t instance;
vector<string> kexisting;
vector<string> kmissing;
map<string, Item> kmap;
vector<lcb_get_cmd_t> cmds;
vector<lcb_get_cmd_t *> cmdptrs;
createConnection(instance);
int iterations = 4;
for (int ii = 0; ii < iterations; ii++) {
char suffix = 'a' + ii;
string k("existingKey");
k += suffix;
kexisting.push_back(k);
storeKey(instance, k, k);
k = "nonExistKey";
k += suffix;
removeKey(instance, k);
kmissing.push_back(k);
}
for (int ii = 0; ii < iterations; ii++) {
lcb_get_cmd_t cmdhit(kexisting[ii].c_str(), kexisting[ii].size());
lcb_get_cmd_t cmdmiss(kmissing[ii].c_str(), kmissing[ii].size());
cmds.push_back(cmdhit);
cmds.push_back(cmdmiss);
}
for (int ii = 0; ii < cmds.size(); ii++) {
cmdptrs.push_back(&cmds[ii]);
}
lcb_set_get_callback(instance, testMixedMultiGetCallback);
EXPECT_EQ(LCB_SUCCESS,
lcb_get(instance, &kmap, cmds.size(), &cmdptrs[0]));
lcb_wait(instance);
ASSERT_EQ(iterations * 2, kmap.size());
for (int ii = 0; ii < iterations; ii++) {
string k = kexisting[ii];
ASSERT_EQ(1, kmap.count(k));
Item itm = kmap[k];
ASSERT_EQ(LCB_SUCCESS, itm.err);
ASSERT_EQ(k, itm.val);
k = kmissing[ii];
ASSERT_EQ(1, kmap.count(k));
itm = kmap[k];
ASSERT_EQ(LCB_KEY_ENOENT, itm.err);
}
}
Jump to Line
Something went wrong with that request. Please try again.