MXS-1401 Add test cases
Test that an array of rules is parsed and used properly.
This commit is contained in:
86
server/modules/filter/cache/rules.cc
vendored
86
server/modules/filter/cache/rules.cc
vendored
@ -429,6 +429,24 @@ std::auto_ptr<CacheRules> CacheRules::create(uint32_t debug)
|
||||
return sThis;
|
||||
}
|
||||
|
||||
// static
|
||||
bool CacheRules::parse(const char* zJson, uint32_t debug, std::vector<SCacheRules>* pRules)
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
pRules->clear();
|
||||
|
||||
CACHE_RULES** ppRules;
|
||||
int32_t nRules;
|
||||
|
||||
if (cache_rules_parse(zJson, debug, &ppRules, &nRules))
|
||||
{
|
||||
rv = create_cache_rules(ppRules, nRules, pRules);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
// static
|
||||
bool CacheRules::load(const char *zPath, uint32_t debug, std::vector<SCacheRules>* pRules)
|
||||
{
|
||||
@ -441,40 +459,50 @@ bool CacheRules::load(const char *zPath, uint32_t debug, std::vector<SCacheRules
|
||||
|
||||
if (cache_rules_load(zPath, debug, &ppRules, &nRules))
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<SCacheRules> rules;
|
||||
rules.reserve(nRules);
|
||||
|
||||
for (int i = 0; i < nRules; ++i)
|
||||
{
|
||||
j = i;
|
||||
CacheRules* pRules = new CacheRules(ppRules[i]);
|
||||
j = i + 1;
|
||||
|
||||
rules.push_back(SCacheRules(pRules));
|
||||
}
|
||||
|
||||
pRules->swap(rules);
|
||||
rv = true;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
// Free all CACHE_RULES objects that were not pushed into 'rules' above.
|
||||
for (; j < nRules; ++j)
|
||||
{
|
||||
cache_rules_free(ppRules[j]);
|
||||
}
|
||||
}
|
||||
|
||||
MXS_FREE(ppRules);
|
||||
rv = create_cache_rules(ppRules, nRules, pRules);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//static
|
||||
bool CacheRules::create_cache_rules(CACHE_RULES** ppRules, int32_t nRules, std::vector<SCacheRules>* pRules)
|
||||
{
|
||||
bool rv = false;
|
||||
|
||||
int j = 0;
|
||||
|
||||
try
|
||||
{
|
||||
std::vector<SCacheRules> rules;
|
||||
rules.reserve(nRules);
|
||||
|
||||
for (int i = 0; i < nRules; ++i)
|
||||
{
|
||||
j = i;
|
||||
CacheRules* pRules = new CacheRules(ppRules[i]);
|
||||
j = i + 1;
|
||||
|
||||
rules.push_back(SCacheRules(pRules));
|
||||
}
|
||||
|
||||
pRules->swap(rules);
|
||||
rv = true;
|
||||
}
|
||||
catch (const std::exception&)
|
||||
{
|
||||
// Free all CACHE_RULES objects that were not pushed into 'rules' above.
|
||||
for (; j < nRules; ++j)
|
||||
{
|
||||
cache_rules_free(ppRules[j]);
|
||||
}
|
||||
}
|
||||
|
||||
MXS_FREE(ppRules);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
const json_t* CacheRules::json() const
|
||||
{
|
||||
return m_pRules->root;
|
||||
|
21
server/modules/filter/cache/rules.h
vendored
21
server/modules/filter/cache/rules.h
vendored
@ -186,6 +186,9 @@ class CacheRules
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<CacheRules> SCacheRules;
|
||||
|
||||
CacheRules(const CacheRules&) = delete;
|
||||
CacheRules& operator = (const CacheRules&) = delete;
|
||||
|
||||
~CacheRules();
|
||||
|
||||
/**
|
||||
@ -198,7 +201,18 @@ public:
|
||||
static std::auto_ptr<CacheRules> create(uint32_t debug);
|
||||
|
||||
/**
|
||||
* Loads the caching rules from a file and returns corresponding object.
|
||||
* Parses the caching rules from a string.
|
||||
*
|
||||
* @param zJson Null-terminate string containing JSON.
|
||||
* @param debug The debug level.
|
||||
* @param pRules [out] The loaded rules.
|
||||
*
|
||||
* @return True, if the rules could be parsed, false otherwise.
|
||||
*/
|
||||
static bool parse(const char* zJson, uint32_t debug, std::vector<SCacheRules>* pRules);
|
||||
|
||||
/**
|
||||
* Loads the caching rules from a file.
|
||||
*
|
||||
* @param path The path of the file containing the rules.
|
||||
* @param debug The debug level.
|
||||
@ -240,8 +254,9 @@ public:
|
||||
private:
|
||||
CacheRules(CACHE_RULES* pRules);
|
||||
|
||||
CacheRules(const CacheRules&);
|
||||
CacheRules& operator = (const CacheRules&);
|
||||
static bool create_cache_rules(CACHE_RULES** ppRules,
|
||||
int32_t nRules,
|
||||
std::vector<SCacheRules>* pRules);
|
||||
|
||||
private:
|
||||
CACHE_RULES* m_pRules;
|
||||
|
125
server/modules/filter/cache/test/testrules.cc
vendored
125
server/modules/filter/cache/test/testrules.cc
vendored
@ -12,7 +12,8 @@
|
||||
*/
|
||||
|
||||
#include "rules.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <maxscale/alloc.h>
|
||||
#include <maxscale/config.h>
|
||||
#include <maxscale/log_manager.h>
|
||||
@ -20,6 +21,8 @@
|
||||
#include <maxscale/protocol/mysql.h>
|
||||
#include <maxscale/query_classifier.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#if !defined(SS_DEBUG)
|
||||
#define SS_DEBUG
|
||||
#endif
|
||||
@ -188,7 +191,7 @@ const struct store_test_case store_test_cases[] =
|
||||
STORE_TEST_CASE("column", "=", "a", true, NULL, "SELECT a, b FROM tbl WHERE a = 5"),
|
||||
};
|
||||
|
||||
const size_t n_store_test_cases = sizeof(store_test_cases) / sizeof(store_test_cases[0]);
|
||||
const int n_store_test_cases = sizeof(store_test_cases) / sizeof(store_test_cases[0]);
|
||||
|
||||
int test_store()
|
||||
{
|
||||
@ -242,12 +245,130 @@ int test_store()
|
||||
}
|
||||
|
||||
|
||||
static const char ARRAY_RULES[] =
|
||||
"["
|
||||
" {"
|
||||
" \"store\": ["
|
||||
" {"
|
||||
" \"attribute\": \"column\","
|
||||
" \"op\": \"=\","
|
||||
" \"value\": \"a\""
|
||||
" }"
|
||||
" ]"
|
||||
" },"
|
||||
" {"
|
||||
" \"store\": ["
|
||||
" {"
|
||||
" \"attribute\": \"column\","
|
||||
" \"op\": \"=\","
|
||||
" \"value\": \"b\""
|
||||
" }"
|
||||
" ]"
|
||||
" },"
|
||||
" {"
|
||||
" \"store\": ["
|
||||
" {"
|
||||
" \"attribute\": \"column\","
|
||||
" \"op\": \"=\","
|
||||
" \"value\": \"c\""
|
||||
" }"
|
||||
" ]"
|
||||
" }"
|
||||
"]";
|
||||
|
||||
struct ARRAY_TEST_CASE
|
||||
{
|
||||
const char* zStmt; // Statement
|
||||
int32_t index; // Index of rule to match, -1 if none.
|
||||
} array_test_cases[] =
|
||||
{
|
||||
{
|
||||
"select a from tbl",
|
||||
0
|
||||
},
|
||||
{
|
||||
"select b from tbl",
|
||||
1
|
||||
},
|
||||
{
|
||||
"select c from tbl",
|
||||
2
|
||||
},
|
||||
{
|
||||
"select a, b from tbl",
|
||||
0
|
||||
},
|
||||
{
|
||||
"select d from tbl",
|
||||
-1
|
||||
}
|
||||
};
|
||||
|
||||
const int n_array_test_cases = sizeof(array_test_cases) / sizeof(array_test_cases[0]);
|
||||
|
||||
int test_array_store()
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
typedef CacheRules::SCacheRules SCacheRules;
|
||||
std::vector<SCacheRules> rules;
|
||||
|
||||
if (CacheRules::parse(ARRAY_RULES, 0, &rules))
|
||||
{
|
||||
for (int i = 0; i < n_array_test_cases; ++i)
|
||||
{
|
||||
const ARRAY_TEST_CASE& tc = array_test_cases[i];
|
||||
|
||||
cout << tc.zStmt << endl;
|
||||
|
||||
GWBUF* pStmt = create_gwbuf(tc.zStmt);
|
||||
auto it = std::find_if(rules.begin(), rules.end(), [pStmt](SCacheRules sRules)
|
||||
{
|
||||
return sRules->should_store(NULL, pStmt);
|
||||
});
|
||||
|
||||
int index = (it == rules.end()) ? -1 : std::distance(rules.begin(), it);
|
||||
|
||||
if (it != rules.end())
|
||||
{
|
||||
if (tc.index == index)
|
||||
{
|
||||
cout << "OK: Rule " << tc.index << " matches as expected." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++errors;
|
||||
cout << "ERROR: Rule " << tc.index << " should have matched, but " << index << " did." << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tc.index == -1)
|
||||
{
|
||||
cout << "OK: No rule matched, as expected." << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
++errors;
|
||||
cout << "ERROR: Rule " << tc.index << " should have matched, but none did." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
int test()
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += test_user();
|
||||
errors += test_store();
|
||||
errors += test_array_store();
|
||||
|
||||
return errors ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
Reference in New Issue
Block a user