/*
* 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 <iostream>
#include "cpixfstools.h"
#include "itk.h"
#include "cpixidxdb.h"
#include "config.h"
#include "testutils.h"
#include "setupsentry.h"
#include "testcorpus.h"
cpix_FieldDesc MultiFieldSchema[] = {
// filter field
{
LCPIX_FILTERID_FIELD, // name_
cpix_STORE_YES | cpix_INDEX_NO, // cfg_
},
// dummy field
{
L"dummy", // name_
cpix_STORE_YES | cpix_INDEX_TOKENIZED // cfg_
},
{
L"dummy2", // name_
cpix_STORE_YES | cpix_INDEX_NO | cpix_AGGREGATE_YES// cfg_
},
{
L"dummy3", // name_
cpix_STORE_YES | cpix_INDEX_TOKENIZED | cpix_AGGREGATE_NO // cfg_
}
};
const wchar_t * DummyWords[] = {
L"happy words",
L"look at you",
L"happening there",
L"important happiness"
};
// NOTE must be of the same size (or bigger) as DummyWords
const wchar_t * Dummy2Words[] = {
L"christmas easter",
L"summer's midnight eve",
L"thanksgiving",
L"vappu"
};
// NOTE must be of the same size (or bigger) as DummyWords
const wchar_t * Dummy3Words[] = {
L"rabid happening",
L"look, important and happy robot",
L"christmas for ever",
L"christmas is an important and happy happening"
};
class MultiFieldIdxUtil : public FileIdxUtil
{
public:
virtual ~MultiFieldIdxUtil() throw ()
{
;
}
void indexMultiField(const char * path,
cpix_Analyzer * analyzer,
Itk::TestMgr * testMgr)
{
wchar_t
wpath[256];
size_t
res = mbstowcs(wpath,
path,
sizeof(wpath) / sizeof(wchar_t) - 1);
ITK_ASSERT(testMgr,
//res >= 0,
1,
"mbstowcs failed, errno: %d",
errno);
wpath[sizeof(wpath) / sizeof(wchar_t) - 1] = wchar_t(0);
static int
dummyWordIdx = 0;
const wchar_t *fields[4] = {
LCPIX_FILEPARSER_FID, // filter id field
DummyWords[dummyWordIdx], // dummy field
Dummy2Words[dummyWordIdx], // dummy2 field
Dummy3Words[dummyWordIdx] // dummy3 field
};
++dummyWordIdx;
if (dummyWordIdx == sizeof(DummyWords) / sizeof(wchar_t*))
{
dummyWordIdx = 0;
}
// NOTE: app class, excerpt and mime type have to be defined
// here, but this is using the file parser functionality
// inside Cpix, which re-defines these anyway
cpix_IdxDb_add2(idxDb(),
schemaId(),
wpath, // docUid,
NULL, // app class
NULL, // excerpt
NULL, // mime type
(const wchar_t**)fields, // fields
analyzer);
if (cpix_Failed(idxDb()))
{
wchar_t
report[256];
cpix_Error_report(idxDb()->err_,
report,
sizeof(report));
ITK_ASSERT(testMgr,
false,
"Failed to add document %S: %S",
wpath,
report);
cpix_ClearError(idxDb());
}
else
{
wpath[0] = '!';
ITK_MSG(testMgr,
"Indexed file (multifield): %S",
wpath);
}
}
protected:
virtual void printHit(cpix_Document * doc,
Itk::TestMgr * testMgr)
{
using namespace std;
std::wstring
idStr(getIdStr(doc,
testMgr));
fprintf(stdout,
"DOC (multifield) (%S):\n",
idStr.c_str());
cpix_DocFieldEnum
* dfe = cpix_Document_fields(doc);
if (cpix_Succeeded(doc))
{
cpix_Field
field;
while (cpix_DocFieldEnum_hasMore(dfe))
{
cpix_DocFieldEnum_next(dfe,
&field);
const wchar_t
* name = cpix_Field_name(&field);
if (wcscmp(name, LCPIX_DOCUID_FIELD) == 0)
{
continue;
}
fprintf(stdout,
" o %S: ",
name);
bool
binary = static_cast<bool>(cpix_Field_isBinary(&field));
fprintf(stdout,
"%S\n",
(binary ?
L"(binary)"
: cpix_Field_stringValue(&field)
)
);
}
cpix_DocFieldEnum_destroy(dfe);
}
else
{
wchar_t
report[128];
cpix_Error_report(doc->err_,
report,
sizeof(report)/sizeof(wchar_t));
ITK_EXPECT(testMgr,
false,
"Could not create doc field enum: %S",
report);
cpix_ClearError(doc);
}
}
virtual SchemaId addSchema() throw (Itk::PanicExc)
{
return cpix_IdxDb_addSchema(idxDb(),
MultiFieldSchema,
sizeof(MultiFieldSchema)/sizeof(cpix_FieldDesc));
}
};
class MultiFieldContext : public Itk::ITestContext, public Cpt::IFileVisitor
{
protected:
MultiFieldIdxUtil * util_;
cpix_Analyzer * analyzer_;
cpix_QueryParser * queryParser_;
Itk::TestMgr * testMgr_;
public:
//
// From ITestContext
//
virtual void setup() throw (Itk::PanicExc)
{
SetupSentry
ss(*this);
cpix_Result
result;
cpix_IdxDb_dbgScrapAll(&result);
using namespace std;
util_ = new MultiFieldIdxUtil;
util_->init();
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");
}
ss.setupComplete();
}
virtual void tearDown() throw ()
{
cleanup();
}
virtual ~MultiFieldContext()
{
cleanup();
}
//
// from Cpt::IFileVisitor
//
virtual bool visitFile(const char * path)
{
bool
goOn = true;
util_->indexMultiField(path,
analyzer_,
testMgr_);
return goOn;
}
virtual DirVisitResult visitDirPre(const char * /* path */)
{
return IFV_CONTINUE;
}
virtual bool visitDirPost(const char * /* path */)
{
return true;
}
MultiFieldContext()
: util_(NULL),
analyzer_(NULL),
queryParser_(NULL),
testMgr_(NULL)
{
;
}
//
// Test operations
//
void testAddFiles(Itk::TestMgr * testMgr)
{
testMgr_ = testMgr;
Cpt::traverse(FILE_TEST_CORPUS_PATH "\\en",
this);
util_->flush();
}
void testSearchForHappy(Itk::TestMgr * testMgr)
{
const wchar_t
* word = L"happy";
testSearchFor(testMgr,
word);
}
void testSearchForImportant(Itk::TestMgr * testMgr)
{
const wchar_t
* word = L"important";
testSearchFor(testMgr,
word);
}
void testSearchForHappening(Itk::TestMgr * testMgr)
{
const wchar_t
* word = L"happening";
testSearchFor(testMgr,
word);
}
void testSearchForLook(Itk::TestMgr * testMgr)
{
const wchar_t
* word = L"look";
testSearchFor(testMgr,
word);
}
void testSearchForChristmas(Itk::TestMgr * testMgr)
{
const wchar_t
* word = L"christmas";
testSearchFor(testMgr,
word);
}
private:
//
// private methods
//
void testSearchFor(Itk::TestMgr * testMgr,
const wchar_t * word)
{
wchar_t
report[512];
cpix_Query
* query = cpix_QueryParser_parse(queryParser_,
word);
if (cpix_Succeeded(queryParser_))
{
cpix_Hits
* hits = cpix_IdxDb_search(util_->idxDb(),
query);
if (cpix_Succeeded(util_->idxDb()))
{
util_->printHits(hits,
testMgr);
}
else
{
cpix_Error_report(util_->idxDb()->err_,
report,
sizeof(report)/sizeof(wchar_t));
ITK_EXPECT(testMgr,
false,
"Failed to search: %S",
report);
cpix_ClearError(util_->idxDb());
}
cpix_Hits_destroy(hits);
}
else
{
cpix_Error_report(query->err_,
report,
sizeof(report)/sizeof(wchar_t));
ITK_EXPECT(testMgr,
false,
"Failed to parse '%S': %S",
word,
report);
cpix_ClearError(query);
}
cpix_Query_destroy(query);
}
void cleanup()
{
delete util_;
util_ = NULL;
cpix_Analyzer_destroy(analyzer_);
analyzer_ = NULL;
cpix_QueryParser_destroy(queryParser_);
queryParser_ = NULL;
}
};
Itk::TesterBase * CreateAggregateTests()
{
using namespace Itk;
MultiFieldContext
* context = new MultiFieldContext;
ContextTester
* contextTester = new ContextTester("aggregate",
context);
#define TEST "adding"
contextTester->add(TEST,
context,
&MultiFieldContext::testAddFiles,
TEST);
#undef TEST
#define TEST "searchHappy"
contextTester->add(TEST,
context,
&MultiFieldContext::testSearchForHappy,
TEST);
#undef TEST
#define TEST "searchImportant"
contextTester->add(TEST,
context,
&MultiFieldContext::testSearchForImportant,
TEST);
#undef TEST
#define TEST "searchHappening"
contextTester->add(TEST,
context,
&MultiFieldContext::testSearchForHappening,
TEST);
#undef TEST
#define TEST "searchLook"
contextTester->add(TEST,
context,
&MultiFieldContext::testSearchForLook,
TEST);
#undef TEST
#define TEST "searchChristmas"
contextTester->add(TEST,
context,
&MultiFieldContext::testSearchForChristmas,
TEST);
#undef TEST
// TODO add more tests to suite
return contextTester;
}