/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
#include <wchar.h>
#include <stddef.h>
#include <memory>
#include <iostream>
#include <list>
#include <map>
#include <vector>
#include "cpixfstools.h"
#include "itk.h"
#include "cpixidxdb.h"
#include "cpixsearch.h"
#include "idxdbmgr.h" // from private folder: whitebox testing
#include "config.h"
#include "suggestion.h"
#include "testutils.h"
#include "testcorpus.h"
#include "setupsentry.h"
struct MatchTest
{
const char * domainSelector_;
const char * baseAppClass_;
};
void testDomainSelection(Itk::TestMgr * testMgr,
const MatchTest * matchTest,
bool shouldMatch)
{
for (; matchTest->domainSelector_ != NULL; ++matchTest)
{
bool
matched = Cpix::IdxDbMgr::match(matchTest->domainSelector_,
matchTest->baseAppClass_);
ITK_EXPECT(testMgr,
matched == shouldMatch,
"Domain selector '%s' and baseappclass: '%s' "
"should %s match",
matchTest->domainSelector_,
matchTest->baseAppClass_,
(shouldMatch ? "" : "NOT"));
}
}
const MatchTest PositiveMatchTests[] = {
// multiple volume cases
{ "root file", "@c:root file" },
{ "root file", "@d:root file" },
{ "@c:root file", "@c:root file" },
{ "@d:root file", "@d:root file" },
// generic/widening search cases
{ "root", "@c:root file" },
{ "root", "@d:root file" },
{ "root", "@0:root msg phone sms" },
{ "root msg", "@0:root msg phone sms" },
{ "@c:root", "@c:root file" },
{ "@d:root", "@d:root file" },
// selecting a list of volumes to use
{ "@FIN:root maps,@GBR:root maps", "@FIN:root maps" },
{ "@FIN:root maps,@GBR:root maps", "@GBR:root maps" },
{ "root file,root msg phone sms", "@c:root file" },
{ "root file,root msg phone sms", "@d:root file" },
{ "root file,root msg phone sms", "@0:root msg phone sms" },
{ "@c:root file,root msg phone sms", "@c:root file" },
{ "@c:root file,root msg phone sms", "@0:root msg phone sms" },
// end
{ NULL, NULL }
};
void testPositiveDomainSelection(Itk::TestMgr * testMgr)
{
testDomainSelection(testMgr,
PositiveMatchTests,
true); // should match
}
const MatchTest NegativeMatchTests[] = {
{ "root file", "@0:root msg phone sms" },
{ "@c:root file", "@0:root msg phone sms" },
{ "root file", "@FIN:root maps" },
{ "@c:root file", "@FIN:root maps" },
// end
{ NULL, NULL }
};
void testNegativeDomainSelection(Itk::TestMgr * testMgr)
{
testDomainSelection(testMgr,
NegativeMatchTests,
false); // should NOT match
}
class DomainSelectionContext : public Itk::ITestContext
{
cpix_Analyzer * analyzer_;
cpix_Query * query_;
cpix_Query * termsQuery_;
cpix_Query * dumpQuery_;
cpix_QueryParser * queryParser_;
std::list<cpix_IdxSearcher*> searchers_;
static const char * domainSpecifiers_[];
static const MVFTest filesAndVols_[];
public:
virtual void setup() throw (Itk::PanicExc)
{
SetupSentry
ss(*this);
cpix_Result
result;
cpix_IdxDb_dbgScrapAll(&result);
if (cpix_Failed(&result))
{
cpix_LogLevel
ll = cpix_setLogLevel(CPIX_LL_TRACE);
cpix_dbgDumpState();
cpix_setLogLevel(ll);
ITK_PANIC("Could not dbg scrapp all indexes");
}
analyzer_ = cpix_CreateSimpleAnalyzer(&result);
if (analyzer_ == NULL)
{
ITK_PANIC("Could not create analyzer");
}
queryParser_ = cpix_QueryParser_create(&result,
LCPIX_DEFAULT_FIELD,
analyzer_);
if (queryParser_ == NULL)
{
ITK_PANIC("Could not create query parser");
}
query_ = cpix_QueryParser_parse(queryParser_,
L"happ*");
if (cpix_Failed(queryParser_))
{
ITK_PANIC("Could not create query parser");
}
// terms (suggestions) query using unified search API
termsQuery_ = cpix_QueryParser_parse(queryParser_,
L"$terms<50>(ha*)");
if (cpix_Failed(queryParser_)
|| termsQuery_ == NULL)
{
ITK_PANIC("Could not parse terms query string");
}
dumpQuery_ = cpix_QueryParser_parse(queryParser_,
L"*");
if (cpix_Failed(queryParser_))
{
ITK_PANIC("Could not parse terms query string");
}
ss.setupComplete();
}
virtual void tearDown() throw()
{
cleanup();
}
DomainSelectionContext()
: analyzer_(NULL),
query_(NULL),
termsQuery_(NULL),
dumpQuery_(NULL),
queryParser_(NULL)
{
;
}
virtual ~DomainSelectionContext()
{
cleanup();
}
void testCreateIdxs(Itk::TestMgr * testMgr)
{
const MVFTest
* mvfTest = filesAndVols_;
for (; mvfTest->qualifiedBaseAppClass_ != NULL; ++mvfTest)
{
using namespace std;
printf("Creating volume %s ...\n",
mvfTest->qualifiedBaseAppClass_);
{
auto_ptr<VolumeFileIdxUtil>
vfiUtil(new VolumeFileIdxUtil(mvfTest));
vfiUtil->init();
vfiUtil->indexFile(mvfTest->textFilePath_,
analyzer_,
testMgr);
}
printf("... created volume %s\n",
mvfTest->qualifiedBaseAppClass_);
}
printf("Indexing some SMS-es\n");
LineTestCorpusRef
corpus(DEFAULT_TEST_CORPUS_PATH);
std::auto_ptr<SmsIdxUtil>
siUtil(new SmsIdxUtil);
siUtil->init();
for (size_t i = 0; i < 200; ++i)
{
std::wstring
body = corpus.item(i);
siUtil->indexSms(i,
body.c_str(),
analyzer_,
testMgr);
if ((i % 5) == 0)
{
ITK_DBGMSG(testMgr,
".");
}
}
siUtil->flush();
searchAll(testMgr);
suggestAll(testMgr);
dumpAll(testMgr);
}
void unmountC(Itk::TestMgr * testMgr)
{
unmount(filesAndVols_[0].qualifiedBaseAppClass_);
searchAll(testMgr);
suggestAll(testMgr);
}
void unmountE(Itk::TestMgr * testMgr)
{
unmount(filesAndVols_[2].qualifiedBaseAppClass_);
searchAll(testMgr);
suggestAll(testMgr);
}
void unmountD(Itk::TestMgr * testMgr)
{
unmount(filesAndVols_[1].qualifiedBaseAppClass_);
searchAll(testMgr);
suggestAll(testMgr);
}
void mountC(Itk::TestMgr * testMgr)
{
mount(testMgr,
filesAndVols_[0].qualifiedBaseAppClass_,
filesAndVols_[0].idxDbPath_);
searchAll(testMgr);
suggestAll(testMgr);
}
void mountE(Itk::TestMgr * testMgr)
{
mount(testMgr,
filesAndVols_[2].qualifiedBaseAppClass_,
filesAndVols_[2].idxDbPath_);
searchAll(testMgr);
suggestAll(testMgr);
}
void mountD(Itk::TestMgr * testMgr)
{
mount(testMgr,
filesAndVols_[1].qualifiedBaseAppClass_,
filesAndVols_[1].idxDbPath_);
searchAll(testMgr);
suggestAll(testMgr);
}
private:
void unmount(const char * baseAppClass)
{
printf("Unmounting volume %s ...\n",
baseAppClass);
cpix_IdxDb_undefineVolume(baseAppClass);
printf("... unmounted volume %s.\n",
baseAppClass);
}
void mount(Itk::TestMgr * testMgr,
const char * baseAppClass,
const char * idxDbPath)
{
printf("mounting volume %s/%s ...\n",
baseAppClass,
idxDbPath);
cpix_Result
result;
cpix_IdxDb_defineVolume(&result,
baseAppClass,
idxDbPath);
ITK_ASSERT(testMgr,
cpix_Succeeded(&result),
"Failed to mount volume %s/%s",
baseAppClass,
idxDbPath);
printf("... mounted volume %s/%s.\n",
baseAppClass,
idxDbPath);
}
void createSearchersIfNecessary(Itk::TestMgr * testMgr)
{
if (searchers_.size() > 0)
{
return;
}
const char
* * domainSpecifierPtr = domainSpecifiers_;
for (; *domainSpecifierPtr != NULL; ++domainSpecifierPtr)
{
cpix_Result
result;
cpix_IdxSearcher
* searcher = cpix_IdxSearcher_openDb(&result,
*domainSpecifierPtr);
ITK_ASSERT(testMgr,
cpix_Succeeded(&result),
"Could not create searcher for '%s'",
*domainSpecifierPtr);
searchers_.push_back(searcher);
}
}
void unifiedSearchAll(Itk::TestMgr * testMgr,
cpix_Query * query,
const char * msg,
void (* printer)(cpix_Hits*, Itk::TestMgr*))
{
createSearchersIfNecessary(testMgr);
printf("\n\n%s\n",
msg);
size_t
idx = 0;
std::list<cpix_IdxSearcher*>::iterator
i = searchers_.begin(),
end = searchers_.end();
for (; i != end; ++i)
{
printf("Searching with domain selector '%s':\n",
domainSpecifiers_[idx]);
cpix_Hits
* hits = cpix_IdxSearcher_search(*i,
query);
ITK_EXPECT(testMgr,
cpix_Succeeded(*i),
"Could not search idx searcher (%s)",
domainSpecifiers_[idx]);
if (cpix_Succeeded(*i))
{
/*
PrintHits(hits,
testMgr);
*/
printer(hits,
testMgr);
}
cpix_Hits_destroy(hits);
printf("\n");
++idx;
}
}
void searchAll(Itk::TestMgr * testMgr)
{
unifiedSearchAll(testMgr,
query_,
"And now searching with all searchers",
&PrintHits);
}
void suggestAll(Itk::TestMgr * testMgr)
{
unifiedSearchAll(testMgr,
termsQuery_,
"And now suggesting for 'ha*' with all searchers",
&Suggestion::printSuggestions);
}
void dumpAll(Itk::TestMgr * testMgr)
{
unifiedSearchAll(testMgr,
dumpQuery_,
"And now dumping with all searchers",
&PrintHits);
}
void cleanup()
{
cpix_Analyzer_destroy(analyzer_);
analyzer_ = NULL;
cpix_Query_destroy(query_);
query_ = NULL;
cpix_Query_destroy(termsQuery_);
termsQuery_ = NULL;
cpix_Query_destroy(dumpQuery_);
dumpQuery_ = NULL;
cpix_QueryParser_destroy(queryParser_);
queryParser_ = NULL;
std::list<cpix_IdxSearcher*>::iterator
i = searchers_.begin(),
end = searchers_.end();
for (; i != end; ++i)
{
cpix_IdxSearcher_releaseDb(*i);
}
searchers_.clear();
}
};
const MVFTest DomainSelectionContext::filesAndVols_[] = {
{
FILE_TEST_CORPUS_PATH "\\en\\1.txt",
"@c:root file",
CPIX_TEST_INDEVICE_INDEXDB_PHMEM CPIX_FILE_IDXDB "_\\c",
},
{
FILE_TEST_CORPUS_PATH "\\en\\2.txt",
"@d:root file",
CPIX_TEST_INDEVICE_INDEXDB_PHMEM CPIX_FILE_IDXDB "_\\d",
},
{
FILE_TEST_CORPUS_PATH "\\en\\3.txt",
"@e:root file",
CPIX_TEST_INDEVICE_INDEXDB_PHMEM CPIX_FILE_IDXDB "_\\e",
},
{
FILE_TEST_CORPUS_PATH "\\en\\4.txt",
"@f:root file",
CPIX_TEST_INDEVICE_INDEXDB_PHMEM CPIX_FILE_IDXDB "_\\f",
},
{
NULL,
NULL,
NULL
},
};
const char * DomainSelectionContext::domainSpecifiers_[] = {
"root",
"root msg",
"@d:root file,root msg phone sms",
"@d:root file,@f:root file",
NULL
};
// TODO implement actual test cases for generic / widening search
// (defining volumes and other stuff and searching them)
// TODO implement actual test cases for selecting list of app classes
// to use
Itk::TesterBase * CreateDomainSelectionTests()
{
using namespace Itk;
SuiteTester
* domainTester = new SuiteTester("domain");
// some white box test testing matcing logic
SuiteTester
* whiteBox = new SuiteTester("whitebox");
#define TEST "positive"
whiteBox->add(TEST,
&testPositiveDomainSelection);
#undef TEST
#define TEST "negative"
whiteBox->add(TEST,
&testNegativeDomainSelection);
#undef TEST
domainTester->add(whiteBox);
// some blackbox tests doing idx manipulation & searches
DomainSelectionContext
* domainSelectionContext = new DomainSelectionContext();
ContextTester
* contextTester = new ContextTester("selection",
domainSelectionContext);
#define TEST "createIdxs"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::testCreateIdxs,
TEST);
#undef TEST
#define TEST "unmountC"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::unmountC,
TEST);
#undef TEST
#define TEST "unmountE"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::unmountE,
TEST);
#undef TEST
#define TEST "unmountD"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::unmountD,
TEST);
#undef TEST
#define TEST "mountC"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::mountC,
TEST);
#undef TEST
#define TEST "mountE"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::mountE,
TEST);
#undef TEST
#define TEST "mountD"
contextTester->add(TEST,
domainSelectionContext,
&DomainSelectionContext::mountD,
TEST);
#undef TEST
domainTester->add(contextTester);
// ... add more
return domainTester;
}