///////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>
//
// See accompanying file COPYING.TXT file for licensing details.
//
///////////////////////////////////////////////////////////////////////////////
#include "test.h"
#include "cache_storage.h"
#include "tcp_cache_server.h"
#include "cache_over_ip.h"
#include "base_cache.h"
#include <booster/intrusive_ptr.h>
#include <cppcms/config.h>
#include "test.h"
#include <iostream>
#include <memory>
#include <time.h>
#ifdef CPPCMS_WIN_NATIVE
#include <windows.h>
void ssleep(int x) { Sleep(x*1000); }
#else
#include <unistd.h>
void ssleep(int x) { sleep(x); }
#endif
void test_cache(booster::intrusive_ptr<cppcms::impl::base_cache> cache,bool test_generators=true)
{
std::string tmp;
std::set<std::string> tags;
TEST(cache->fetch("foo",tmp,0)==false);
time_t t_and_1=time(0)+1,ttmp=0;
cache->store("foo","bar",tags,t_and_1);
TEST(cache->fetch("foo",tmp,&tags)==true);
TEST(tmp=="bar");
TEST(tags.size()==1);
TEST(tags.find("foo")!=tags.end());
TEST(cache->fetch("foo",0,0,&ttmp)==true);
TEST(ttmp==t_and_1);
ssleep(2);
TEST(cache->fetch("foo",tmp,0)==false);
tags.clear();
cache->clear();
tags.insert("beep");
cache->store("foo","bar",tags,time(0)+5);
cache->store("bar","foo",tags,time(0)+5);
tags.clear();
cache->store("bee","bzzz",tags,time(0)+5);
TEST(cache->fetch("foo",tmp,0) && tmp=="bar");
TEST(cache->fetch("bar",tmp,0) && tmp=="foo");
TEST(cache->fetch("bee",tmp,0) && tmp=="bzzz");
unsigned keys=0,triggers=0;
cache->stats(keys,triggers);
TEST(keys==3 && triggers==5);
cache->rise("beep");
cache->stats(keys,triggers);
TEST(keys==1 && triggers==1);
TEST(cache->fetch("foo",tmp,0)==false);
TEST(cache->fetch("bar",tmp,0)==false);
TEST(cache->fetch("bee",tmp,0) && tmp=="bzzz");
cache->clear();
tags.clear();
cache->store("fu","fu",tags,time(0)+25);
// 25 - make sure it works on slow platforms like
// ARM emulator
for(unsigned i=0;i<1000;i++) {
std::ostringstream key;
key << i;
cache->store(key.str(),key.str(),tags,time(0)+5);
TEST(cache->fetch("fu",tmp,0) && tmp=="fu");
}
TEST(cache->fetch("fu",tmp,0) && tmp=="fu");
TEST(cache->fetch("1",tmp,0)==false);
TEST(cache->fetch("999",tmp,0)==true && tmp=="999");
cache->clear();
tags.clear();
if(test_generators) {
cache->store("test","test",tags,time(0)+5);
cppcms::uint64_t my_gen=2;
cache->store("test2","x",tags,time(0)+5,&my_gen);
cppcms::uint64_t g1=0,g2=0,g3=0;
TEST(cache->fetch("test",0,0,0,&g1));
cache->store("test","test2",tags,time(0)+5);
TEST(cache->fetch("test",&tmp,0,0,&g2));
TEST(tmp=="test2");
TEST(g1!=0 && g2!=0 && g1!=g2);
TEST(cache->fetch("test2",0,0,0,&g3));
TEST(g3==my_gen);
cache->clear();
}
}
void test_two_clients(booster::intrusive_ptr<cppcms::impl::base_cache> c1,booster::intrusive_ptr<cppcms::impl::base_cache> c2)
{
std::string tmp;
std::set<std::string> tags;
c1->store("foo","test",tags,time(0)+1);
TEST(c2->fetch("foo",tmp,0));
TEST(tmp=="test");
c2->store("foo","test2",tags,time(0)+1);
TEST(c1->fetch("foo",tmp,0) && tmp=="test2");
c2->rise("foo");
TEST(c1->fetch("foo",tmp,0)==false);
c2->store("foo","test3",tags,time(0)+1);
TEST(c1->fetch("foo",tmp,0) && tmp=="test3");
c2->clear();
TEST(c1->fetch("foo",tmp,0)==false);
}
int main()
{
typedef booster::shared_ptr<cppcms::sessions::session_storage_factory> sfact_type;
try {
std::cout << "Testing thread cache... "<< std::flush;
test_cache(cppcms::impl::thread_cache_factory(20));
std::cout << "Ok" << std::endl;
#if !defined(CPPCMS_WIN32) && !defined(CPPCMS_NO_PREFOK_CACHE)
std::cout << "Testing process cache... " << std::flush;
test_cache(cppcms::impl::process_cache_factory(16*1024,20));
std::cout << "Ok" << std::endl;
#endif
std::auto_ptr<cppcms::impl::tcp_cache_service> srv1,srv2;
{
try {
std::cout << "Testing cache over ip, single server... "<<std::flush;
std::vector<std::string> ips;
std::vector<int> ports;
ips.push_back("127.0.0.1");
ports.push_back(6001);
srv1.reset(new cppcms::impl::tcp_cache_service(
cppcms::impl::thread_cache_factory(20),
sfact_type(),
1,"127.0.0.1",6001));
test_cache(cppcms::impl::tcp_cache_factory(ips,ports,0),false);
std::cout << "Ok" << std::endl;
std::cout << "Testing cache over ip, single server with L1 cache... "<<std::flush;
test_cache(cppcms::impl::tcp_cache_factory(ips,ports,cppcms::impl::thread_cache_factory(5)),false);
std::cout << "Ok" << std::endl;
srv2.reset(new cppcms::impl::tcp_cache_service(
cppcms::impl::thread_cache_factory(20),
sfact_type(),
1,"127.0.0.1",6002));
ips.push_back("127.0.0.1");
ports.push_back(6002);
std::cout << "Testing cache over ip, multiple server... "<<std::flush;
test_cache(cppcms::impl::tcp_cache_factory(ips,ports,0),false);
std::cout << "Ok" << std::endl;
std::cout << "Testing cache over ip, multiple server with L1 cache... "<<std::flush;
test_cache(cppcms::impl::tcp_cache_factory(ips,ports,cppcms::impl::thread_cache_factory(5)),false);
std::cout << "Ok" <<std::endl;
ips.resize(1);
ports.resize(1);
std::cout << "Testing two clients... "<<std::flush;
test_two_clients(
cppcms::impl::tcp_cache_factory(ips,ports,cppcms::impl::thread_cache_factory(5)),
cppcms::impl::tcp_cache_factory(ips,ports,cppcms::impl::thread_cache_factory(5)));
std::cout << "Ok" <<std::endl;
std::cout << "Testing two clients with L1 cache... "<<std::flush;
test_two_clients(
cppcms::impl::tcp_cache_factory(ips,ports,0),
cppcms::impl::tcp_cache_factory(ips,ports,0));
std::cout << "Ok" <<std::endl;
}
catch(...) {
if(srv1.get()) {
srv1->stop();
srv1.reset();
}
if(srv2.get()) {
srv2->stop();
srv2.reset();
}
throw;
}
srv1->stop();
srv2->stop();
}
}
catch(std::exception const &e) {
std::cerr << "\nFail " << e.what() << std::endl;
return 1;
}
return 0;
}