diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2016-06-15 23:09:44 +0200 |
commit | 72231250ed81e10d66bfe70701e64fa5fe50f712 (patch) | |
tree | 2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /searchsummary/src/tests |
Publish
Diffstat (limited to 'searchsummary/src/tests')
47 files changed, 1841 insertions, 0 deletions
diff --git a/searchsummary/src/tests/docsumformat/.gitignore b/searchsummary/src/tests/docsumformat/.gitignore new file mode 100644 index 00000000000..2c841cbd43d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/.gitignore @@ -0,0 +1,21 @@ +*.cfg +*.core +*.ilk +*.out +*.pdb +*.pid +.depend +Makefile +core +core.* +datapart.* +docsum-index +docsum-pack +docsum-parse +index.cf +merged +meta-info.txt +schema.txt +summary.cf +version.txt +searchsummary_docsum-pack_app diff --git a/searchsummary/src/tests/docsumformat/CMakeLists.txt b/searchsummary/src/tests/docsumformat/CMakeLists.txt new file mode 100644 index 00000000000..ac8d2151792 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchsummary_docsum-pack_app + SOURCES + docsum-pack.cpp + DEPENDS + searchsummary +) +vespa_add_test(NAME searchsummary_docsum-pack_app COMMAND searchsummary_docsum-pack_app) diff --git a/searchsummary/src/tests/docsumformat/docsum-index.sh b/searchsummary/src/tests/docsumformat/docsum-index.sh new file mode 100755 index 00000000000..0d313191685 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/docsum-index.sh @@ -0,0 +1,16 @@ +#!/bin/sh -e +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +findex=../../../bin/findex + +echo "CLEAN" +rm -f index.cf +rm -f summary.cf +rm -rf merged +rm -rf datapart.* + +echo "DOCSUM-INDEX" +./docsum-index + +echo "AUTOINDEX" +$findex autoindex diff --git a/searchsummary/src/tests/docsumformat/docsum-pack.cpp b/searchsummary/src/tests/docsumformat/docsum-pack.cpp new file mode 100644 index 00000000000..3f1b088bd12 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/docsum-pack.cpp @@ -0,0 +1,631 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright (C) 2001-2003 Fast Search & Transfer ASA +// Copyright (C) 2003 Overture Services Norway AS + + +#include <vespa/fastos/fastos.h> +#include <vespa/log/log.h> +LOG_SETUP("docsum-pack"); +#include <vespa/searchlib/util/rawbuf.h> +#include <vespa/searchsummary/docsummary/urlresult.h> +#include <vespa/searchsummary/docsummary/resultconfig.h> +#include <vespa/searchsummary/docsummary/resultpacker.h> + +using namespace search::docsummary; + + +// needed to resolve external symbol from httpd.h on AIX +void FastS_block_usr2() {} + + +class MyApp : public FastOS_Application +{ +private: + bool _rc; + uint32_t _cnt; + search::docsummary::ResultConfig _config; + search::docsummary::ResultPacker _packer; + +public: + MyApp() + : _rc(false), + _cnt(0u), + _config(), + _packer(&_config) + { + } + + // log test results + void ReportTestResult(uint32_t line, bool rc); + bool RTR(uint32_t line, bool rc) + { ReportTestResult(line, rc); return rc; } + + // compare runtime info (,but ignore result class) + bool Equal(search::docsummary::ResEntry *a, search::docsummary::ResEntry *b); + bool Equal(search::docsummary::GeneralResult *a, search::docsummary::GeneralResult *b); + + void TestFieldIndex(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, int idx); + + void TestIntValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, uint32_t value); + + void TestDoubleValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, double value); + + void TestInt64Value(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, uint64_t value); + + void TestStringValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, const char *value); + + void TestDataValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, const char *value); + + void TestBasic(); + void TestFailLong(); + void TestFailShort(); + void TestFailOrder(); + void TestCompress(); + void TestCompat(); + void TestBasicInplace(); + void TestCompressInplace(); + + int Main(); +}; + + +void +MyApp::ReportTestResult(uint32_t line, bool rc) +{ + _cnt++; + + if (rc) { + LOG(info, "Test case %d: SUCCESS", _cnt); + } else { + LOG(error, "Test case %d: FAIL (see %s:%d)", _cnt, __FILE__, line); + _rc = false; + } +} + + +bool +MyApp::Equal(search::docsummary::ResEntry *a, search::docsummary::ResEntry *b) +{ + if (a->_type != b->_type) + return false; + + if (a->_intval != b->_intval) + return false; + + if (a->_type != RES_INT && + memcmp(a->_pt, b->_pt, a->_intval) != 0) + return false; + + return true; +} + + +bool +MyApp::Equal(search::docsummary::GeneralResult *a, search::docsummary::GeneralResult *b) +{ + uint32_t numEntries = a->GetClass()->GetNumEntries(); + + if (b->GetClass()->GetNumEntries() != numEntries) + return false; + + for (uint32_t i = 0; i < numEntries; i++) { + + if (!Equal(a->GetEntry(i), b->GetEntry(i))) + return false; + + if (a->GetClass()->GetEntry(i)->_bindname != b->GetClass()->GetEntry(i)->_bindname) + return false; + } + + return true; +} + + +void +MyApp::TestFieldIndex(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, int idx) +{ + bool rc = (gres != NULL && + gres->GetClass()->GetIndexFromName(field) == idx); + + RTR(line, rc); +} + + +void +MyApp::TestIntValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, uint32_t value) +{ + search::docsummary::ResEntry *entry + = (gres != NULL) ? gres->GetEntry(field) : NULL; + + bool rc = (entry != NULL && + entry->_type == RES_INT && + entry->_intval == value); + + RTR(line, rc); +} + + +void +MyApp::TestDoubleValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, double value) +{ + search::docsummary::ResEntry *entry + = (gres != NULL) ? gres->GetEntry(field) : NULL; + + bool rc = (entry != NULL && + entry->_type == RES_DOUBLE && + entry->_doubleval == value); + + RTR(line, rc); +} + + +void +MyApp::TestInt64Value(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, uint64_t value) +{ + search::docsummary::ResEntry *entry + = (gres != NULL) ? gres->GetEntry(field) : NULL; + + bool rc = (entry != NULL && + entry->_type == RES_INT64 && + entry->_int64val == value); + + RTR(line, rc); +} + + +void +MyApp::TestStringValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, const char *value) +{ + search::docsummary::ResEntry *entry + = (gres != NULL) ? gres->GetEntry(field) : NULL; + + bool rc = (entry != NULL && + entry->_type == RES_STRING && + entry->_stringlen == strlen(value) && + strncmp(entry->_stringval, value, entry->_stringlen) == 0); + + if (!rc && entry != NULL) { + LOG(warning, + "string value '%.*s' != '%s'", + (int) entry->_stringlen, + entry->_stringval, value); + } + + RTR(line, rc); +} + + +void +MyApp::TestDataValue(uint32_t line, search::docsummary::GeneralResult *gres, + const char *field, const char *value) +{ + search::docsummary::ResEntry *entry + = (gres != NULL) ? gres->GetEntry(field) : NULL; + + bool rc = (entry != NULL && + entry->_type == RES_DATA && + entry->_datalen == strlen(value) && + strncmp(entry->_dataval, value, entry->_datalen) == 0); + + RTR(line, rc); +} + + +void +MyApp::TestBasic() +{ + const char *buf; + uint32_t buflen; + + search::docsummary::urlresult *res; + search::docsummary::GeneralResult *gres; + + uint32_t intval = 4; + uint16_t shortval = 2; + uint8_t byteval = 1; + float floatval = 4.5; + double doubleval = 8.75; + uint64_t int64val = 8; + const char *strval = "This is a string"; + const char *datval = "This is data"; + const char *lstrval = "This is a long string"; + const char *ldatval = "This is long data"; + + RTR(__LINE__, _packer.Init(0)); + RTR(__LINE__, _packer.AddInteger(intval)); + RTR(__LINE__, _packer.AddShort(shortval)); + RTR(__LINE__, _packer.AddByte(byteval)); + RTR(__LINE__, _packer.AddFloat(floatval)); + RTR(__LINE__, _packer.AddDouble(doubleval)); + RTR(__LINE__, _packer.AddInt64(int64val)); + RTR(__LINE__, _packer.AddString(strval, strlen(strval))); + RTR(__LINE__, _packer.AddData(datval, strlen(datval))); + RTR(__LINE__, _packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, _packer.AddLongData(ldatval, strlen(ldatval))); + RTR(__LINE__, _packer.GetDocsumBlob(&buf, &buflen)); + + res = _config.Unpack(0, 0, 0, buf, buflen); + gres = res->IsGeneral() ? (search::docsummary::GeneralResult *) res : NULL; + + RTR(__LINE__, gres != NULL); + TestIntValue (__LINE__, gres, "integer", 4); + TestIntValue (__LINE__, gres, "short", 2); + TestIntValue (__LINE__, gres, "byte", 1); + TestDoubleValue(__LINE__, gres, "float", floatval); + TestDoubleValue(__LINE__, gres, "double", doubleval); + TestInt64Value (__LINE__, gres, "int64", int64val); + TestStringValue(__LINE__, gres, "string", strval); + TestDataValue (__LINE__, gres, "data", datval); + TestStringValue(__LINE__, gres, "longstring", lstrval); + TestDataValue (__LINE__, gres, "longdata", ldatval); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetNumEntries() == 10)); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetClassID() == 0)); + delete res; +} + + +void +MyApp::TestFailLong() +{ + const char *buf; + uint32_t buflen; + + uint32_t intval = 4; + uint16_t shortval = 2; + uint8_t byteval = 1; + float floatval = 4.5; + double doubleval = 8.75; + uint64_t int64val = 8; + const char *strval = "This is a string"; + const char *datval = "This is data"; + const char *lstrval = "This is a long string"; + const char *ldatval = "This is long data"; + + RTR(__LINE__, _packer.Init(0)); + RTR(__LINE__, _packer.AddInteger(intval)); + RTR(__LINE__, _packer.AddShort(shortval)); + RTR(__LINE__, _packer.AddByte(byteval)); + RTR(__LINE__, _packer.AddFloat(floatval)); + RTR(__LINE__, _packer.AddDouble(doubleval)); + RTR(__LINE__, _packer.AddInt64(int64val)); + RTR(__LINE__, _packer.AddString(strval, strlen(strval))); + RTR(__LINE__, _packer.AddData(datval, strlen(datval))); + RTR(__LINE__, _packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, _packer.AddLongData(ldatval, strlen(ldatval))); + RTR(__LINE__, !_packer.AddByte(byteval)); + RTR(__LINE__, !_packer.GetDocsumBlob(&buf, &buflen)); +} + + +void +MyApp::TestFailShort() +{ + const char *buf; + uint32_t buflen; + + uint32_t intval = 4; + uint16_t shortval = 2; + uint8_t byteval = 1; + float floatval = 4.5; + double doubleval = 8.75; + uint64_t int64val = 8; + const char *strval = "This is a string"; + const char *datval = "This is data"; + const char *lstrval = "This is a long string"; + + RTR(__LINE__, _packer.Init(0)); + RTR(__LINE__, _packer.AddInteger(intval)); + RTR(__LINE__, _packer.AddShort(shortval)); + RTR(__LINE__, _packer.AddByte(byteval)); + RTR(__LINE__, _packer.AddFloat(floatval)); + RTR(__LINE__, _packer.AddDouble(doubleval)); + RTR(__LINE__, _packer.AddInt64(int64val)); + RTR(__LINE__, _packer.AddString(strval, strlen(strval))); + RTR(__LINE__, _packer.AddData(datval, strlen(datval))); + RTR(__LINE__, _packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, !_packer.GetDocsumBlob(&buf, &buflen)); +} + + +void +MyApp::TestFailOrder() +{ + const char *buf; + uint32_t buflen; + + uint32_t intval = 4; + uint16_t shortval = 2; + uint8_t byteval = 1; + float floatval = 4.5; + double doubleval = 8.75; + uint64_t int64val = 8; + const char *strval = "This is a string"; + const char *datval = "This is data"; + const char *lstrval = "This is a long string"; + const char *ldatval = "This is long data"; + + RTR(__LINE__, _packer.Init(0)); + RTR(__LINE__, _packer.AddInteger(intval)); + RTR(__LINE__, _packer.AddShort(shortval)); + RTR(__LINE__, !_packer.AddString(strval, strlen(strval))); + RTR(__LINE__, !_packer.AddByte(byteval)); + RTR(__LINE__, !_packer.AddFloat(floatval)); + RTR(__LINE__, !_packer.AddDouble(doubleval)); + RTR(__LINE__, !_packer.AddInt64(int64val)); + RTR(__LINE__, !_packer.AddData(datval, strlen(datval))); + RTR(__LINE__, !_packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, !_packer.AddLongData(ldatval, strlen(ldatval))); + RTR(__LINE__, !_packer.GetDocsumBlob(&buf, &buflen)); +} + + +void +MyApp::TestCompress() +{ + const char *buf; + uint32_t buflen; + + search::docsummary::urlresult *res; + search::docsummary::GeneralResult *gres; + + const char *lstrval = "string string string"; + const char *ldatval = "data data data"; + + RTR(__LINE__, _packer.Init(2)); + RTR(__LINE__, _packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, _packer.AddLongData(ldatval, strlen(ldatval))); + RTR(__LINE__, _packer.GetDocsumBlob(&buf, &buflen)); + + res = _config.Unpack(0, 0, 0, buf, buflen); + gres = res->IsGeneral() ? (search::docsummary::GeneralResult *) res : NULL; + + RTR(__LINE__, gres != NULL); + TestStringValue(__LINE__, gres, "text", lstrval); + TestDataValue (__LINE__, gres, "data", ldatval); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetNumEntries() == 2)); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetClassID() == 2)); + delete res; +} + + +void +MyApp::TestCompat() +{ + const char *buf; + uint32_t buflen; + + search::docsummary::urlresult *res1; + search::docsummary::GeneralResult *gres1; + + search::docsummary::urlresult *res2; + search::docsummary::GeneralResult *gres2; + + const char *strval = "string string string string"; + const char *datval = "data data data data"; + + RTR(__LINE__, _packer.Init(1)); + RTR(__LINE__, _packer.AddData(strval, strlen(strval))); + RTR(__LINE__, _packer.AddString(datval, strlen(datval))); + RTR(__LINE__, _packer.GetDocsumBlob(&buf, &buflen)); + res1 = _config.Unpack(0, 0, 0, buf, buflen); + gres1 = res1->IsGeneral() ? (search::docsummary::GeneralResult *) res1 : NULL; + + RTR(__LINE__, _packer.Init(2)); + RTR(__LINE__, _packer.AddLongData(strval, strlen(strval))); + RTR(__LINE__, _packer.AddLongString(datval, strlen(datval))); + RTR(__LINE__, _packer.GetDocsumBlob(&buf, &buflen)); + res2 = _config.Unpack(0, 0, 0, buf, buflen); + gres2 = res2->IsGeneral() ? (search::docsummary::GeneralResult *) res2 : NULL; + + RTR(__LINE__, gres1 != NULL); + RTR(__LINE__, gres2 != NULL); + + TestStringValue(__LINE__, gres1, "text", strval); + TestDataValue (__LINE__, gres1, "data", datval); + TestFieldIndex (__LINE__, gres1, "text", 0); + TestFieldIndex (__LINE__, gres1, "data", 1); + RTR(__LINE__, (gres1 != NULL && + gres1->GetClass()->GetNumEntries() == 2)); + + TestStringValue(__LINE__, gres2, "text", strval); + TestDataValue (__LINE__, gres2, "data", datval); + TestFieldIndex (__LINE__, gres2, "text", 0); + TestFieldIndex (__LINE__, gres2, "data", 1); + RTR(__LINE__, (gres2 != NULL && + gres2->GetClass()->GetNumEntries() == 2)); + + RTR(__LINE__, (gres1 != NULL && + gres1->GetClass()->GetClassID() == 1)); + RTR(__LINE__, (gres2 != NULL && + gres2->GetClass()->GetClassID() == 2)); + + RTR(__LINE__, (gres1 != NULL && gres2 != NULL && + Equal(gres1, gres2))); + + delete res1; + delete res2; +} + + +void +MyApp::TestBasicInplace() +{ + const char *buf; + uint32_t buflen; + + const search::docsummary::ResultClass *resClass; + search::docsummary::GeneralResult *gres; + + uint32_t intval = 4; + uint16_t shortval = 2; + uint8_t byteval = 1; + float floatval = 4.5; + double doubleval = 8.75; + uint64_t int64val = 8; + const char *strval = "This is a string"; + const char *datval = "This is data"; + const char *lstrval = "This is a long string"; + const char *ldatval = "This is long data"; + + RTR(__LINE__, _packer.Init(0)); + RTR(__LINE__, _packer.AddInteger(intval)); + RTR(__LINE__, _packer.AddShort(shortval)); + RTR(__LINE__, _packer.AddByte(byteval)); + RTR(__LINE__, _packer.AddFloat(floatval)); + RTR(__LINE__, _packer.AddDouble(doubleval)); + RTR(__LINE__, _packer.AddInt64(int64val)); + RTR(__LINE__, _packer.AddString(strval, strlen(strval))); + RTR(__LINE__, _packer.AddData(datval, strlen(datval))); + RTR(__LINE__, _packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, _packer.AddLongData(ldatval, strlen(ldatval))); + RTR(__LINE__, _packer.GetDocsumBlob(&buf, &buflen)); + + resClass = _config.LookupResultClass(_config.GetClassID(buf, buflen)); + if (resClass == NULL) { + gres = NULL; + } else { + DocsumStoreValue value(buf, buflen); + gres = new search::docsummary::GeneralResult(resClass, 0, 0, 0); + if (!gres->inplaceUnpack(value)) { + delete gres; + gres = NULL; + } + } + + RTR(__LINE__, gres != NULL); + TestIntValue (__LINE__, gres, "integer", 4); + TestIntValue (__LINE__, gres, "short", 2); + TestIntValue (__LINE__, gres, "byte", 1); + TestDoubleValue(__LINE__, gres, "float", floatval); + TestDoubleValue(__LINE__, gres, "double", doubleval); + TestInt64Value (__LINE__, gres, "int64", int64val); + TestStringValue(__LINE__, gres, "string", strval); + TestDataValue (__LINE__, gres, "data", datval); + TestStringValue(__LINE__, gres, "longstring", lstrval); + TestDataValue (__LINE__, gres, "longdata", ldatval); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetNumEntries() == 10)); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetClassID() == 0)); + delete gres; +} + + +void +MyApp::TestCompressInplace() +{ + const char *buf; + uint32_t buflen; + + search::RawBuf field1(32768); + search::RawBuf field2(32768); + const search::docsummary::ResultClass *resClass; + search::docsummary::GeneralResult *gres; + + const char *lstrval = "string string string"; + const char *ldatval = "data data data"; + + RTR(__LINE__, _packer.Init(2)); + RTR(__LINE__, _packer.AddLongString(lstrval, strlen(lstrval))); + RTR(__LINE__, _packer.AddLongData(ldatval, strlen(ldatval))); + RTR(__LINE__, _packer.GetDocsumBlob(&buf, &buflen)); + + resClass = _config.LookupResultClass(_config.GetClassID(buf, buflen)); + if (resClass == NULL) { + gres = NULL; + } else { + DocsumStoreValue value(buf, buflen); + gres = new search::docsummary::GeneralResult(resClass, 0, 0, 0); + if (!gres->inplaceUnpack(value)) { + delete gres; + gres = NULL; + } + } + + search::docsummary::ResEntry *e1 = (gres == NULL) ? NULL : gres->GetEntry("text"); + search::docsummary::ResEntry *e2 = (gres == NULL) ? NULL : gres->GetEntry("data"); + + if (e1 != NULL) + e1->_extract_field(&field1); + if (e2 != NULL) + e2->_extract_field(&field2); + + RTR(__LINE__, gres != NULL); + RTR(__LINE__, e1 != NULL); + RTR(__LINE__, e2 != NULL); + RTR(__LINE__, strcmp(field1.GetDrainPos(), lstrval) == 0); + RTR(__LINE__, strcmp(field2.GetDrainPos(), ldatval) == 0); + RTR(__LINE__, strlen(lstrval) == field1.GetUsedLen()); + RTR(__LINE__, strlen(ldatval) == field2.GetUsedLen()); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetNumEntries() == 2)); + RTR(__LINE__, (gres != NULL && + gres->GetClass()->GetClassID() == 2)); + delete gres; +} + + + +int +MyApp::Main() +{ + _rc = true; + _cnt = 0; + + search::docsummary::ResultClass *resClass; + + resClass = _config.AddResultClass("c0", 0); + resClass->AddConfigEntry("integer", RES_INT); + resClass->AddConfigEntry("short", RES_SHORT); + resClass->AddConfigEntry("byte", RES_BYTE); + resClass->AddConfigEntry("float", RES_FLOAT); + resClass->AddConfigEntry("double", RES_DOUBLE); + resClass->AddConfigEntry("int64", RES_INT64); + resClass->AddConfigEntry("string", RES_STRING); + resClass->AddConfigEntry("data", RES_DATA); + resClass->AddConfigEntry("longstring", RES_LONG_STRING); + resClass->AddConfigEntry("longdata", RES_LONG_DATA); + + resClass = _config.AddResultClass("c1", 1); + resClass->AddConfigEntry("text", RES_STRING); + resClass->AddConfigEntry("data", RES_DATA); + + resClass = _config.AddResultClass("c2", 2); + resClass->AddConfigEntry("text", RES_LONG_STRING); + resClass->AddConfigEntry("data", RES_LONG_DATA); + + TestBasic(); + TestFailLong(); + TestFailShort(); + TestFailOrder(); + TestCompress(); + TestCompat(); + TestBasicInplace(); + TestCompressInplace(); + + LOG(info, "CONCLUSION: %s", (_rc) ? "SUCCESS" : "FAIL"); + return (_rc ? 0 : 1); +} + + +int +main(int argc, char **argv) +{ + MyApp myapp; + return myapp.Entry(argc, argv); +} diff --git a/searchsummary/src/tests/docsumformat/docsum-parse.cpp b/searchsummary/src/tests/docsumformat/docsum-parse.cpp new file mode 100644 index 00000000000..5fa7009464c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/docsum-parse.cpp @@ -0,0 +1,201 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright (C) 2001-2003 Fast Search & Transfer ASA +// Copyright (C) 2003 Overture Services Norway AS + + +#include <vespa/fastos/fastos.h> +#include <vespa/log/log.h> +LOG_SETUP("docsum-parse"); +#include <vespa/fnet/frt/frt.h> +#include <vespa/fastlib/io/bufferedfile.h> +#include <vespa/searchsummary/docsummary/urlresult.h> +#include <vespa/searchsummary/docsummary/resultconfig.h> + + +// needed to resolve external symbol from httpd.h on AIX +void FastS_block_usr2() {} + + +class MyApp : public FastOS_Application +{ +public: + bool Equal(search::docsummary::ResConfigEntry *a, search::docsummary::ResConfigEntry *b); + bool Equal(search::docsummary::ResultClass *a, search::docsummary::ResultClass *b); + bool Equal(search::docsummary::ResultConfig *a, search::docsummary::ResultConfig *b); + bool TestCorrect(const char *dirname, const char *filename); + bool TestIncorrect(const char *dirname, const char *filename); + int Main(); +}; + + +bool +MyApp::Equal(search::docsummary::ResConfigEntry *a, search::docsummary::ResConfigEntry *b) +{ + return ((a->_type == b->_type) + && (strcmp(a->_bindname, b->_bindname) == 0)); +} + + +bool +MyApp::Equal(search::docsummary::ResultClass *a, search::docsummary::ResultClass *b) +{ + bool rc = true; + + rc = rc && (a->GetNumEntries() == b->GetNumEntries()); + rc = rc && (a->GetClassID() == b->GetClassID()); + rc = rc && (strcmp(a->GetClassName(), b->GetClassName()) == 0); + + for (uint32_t i = 0; rc && i < a->GetNumEntries(); i++) { + rc = rc && Equal(a->GetEntry(i), b->GetEntry(i)); + } + + return rc; +} + + +bool +MyApp::Equal(search::docsummary::ResultConfig *a, search::docsummary::ResultConfig *b) +{ + bool rc = true; + + search::docsummary::ResultClass *resClassA; + search::docsummary::ResultClass *resClassB; + + rc = rc && (a->GetNumResultClasses() == b->GetNumResultClasses()); + + resClassA = a->GetResultClasses(); + resClassB = b->GetResultClasses(); + + while(rc && resClassA != NULL && resClassB != NULL) { + rc = rc && Equal(resClassA, resClassB); + resClassA = resClassA->GetNextClass(); + resClassB = resClassB->GetNextClass(); + } + rc = rc && (resClassA == NULL); + rc = rc && (resClassB == NULL); + + return rc; +} + + +bool +MyApp::TestCorrect(const char *dirname, const char *filename) +{ + char str1[512]; // test input file + char str2[512]; // test output file + char str3[512]; // summary.cf verification file + + search::docsummary::ResultConfig a; + search::docsummary::ResultConfig b; + search::docsummary::ResultConfig c; + search::docsummary::ResultConfig d; + + sprintf(str1, "%s%s%s", dirname, + FastOS_FileInterface::GetPathSeparator(), filename); + sprintf(str2, "%s%sout.%s", dirname, + FastOS_FileInterface::GetPathSeparator(), filename); + sprintf(str3, "%s%sOK.%s", dirname, + FastOS_FileInterface::GetPathSeparator(), filename); + + if (!a.ReadConfig(str1)) { + LOG(error, "could not read config from : %s", str1); + return false; + } + + if (!a.WriteConfig(str2)) { + LOG(error, "could not write config to : %s", str2); + return false; + } + + if (!b.ReadConfig(str2)) { + LOG(error, "could not read config from : %s", str2); + return false; + } + + if (!c.ReadConfig(str3)) { + LOG(error, "could not read config from : %s", str3); + return false; + } + + if (!Equal(&a, &b)) { + LOG(error, "%s and %s does not contain the same config", str1, str2); + return false; + } + + if (!Equal(&a, &c)) { + LOG(error, "%s and %s does not contain the same config", str1, str3); + return false; + } + + if (!Equal(&b, &c)) { + LOG(error, "%s and %s does not contain the same config", str2, str3); + return false; + } + + FRT_RPCRequest *req = new FRT_RPCRequest(); + assert(req != NULL); + c.GetConfig(req); + d.SetConfig(req); + if (!Equal(&c, &d)) { + LOG(error, "RPC get/set failed (%s)", str3); + req->SubRef(); + return false; + } + req->SubRef(); + + return true; +} + + +bool +MyApp::TestIncorrect(const char *dirname, const char *filename) +{ + char str[512]; + + sprintf(str, "%s%s%s", dirname, + FastOS_FileInterface::GetPathSeparator(), filename); + + search::docsummary::ResultConfig resConfig; + + if (resConfig.ReadConfig(str)) { + LOG(error, "'%s' did not give parse error", str); + return false; + } + return true; +} + + +int +MyApp::Main() +{ + bool rc = true; + + FastOS_DirectoryScan dirScan("parsetest"); + LOG(info, "looking for input files in 'parsetest'..."); + while (dirScan.ReadNext()) { + if (strncmp(dirScan.GetName(), "correct.", 8) == 0) { + if (TestCorrect("parsetest", dirScan.GetName())) { + LOG(info, "'%s' : positive test PASSED", dirScan.GetName()); + } else { + LOG(error, "'%s' : positive test FAILED", dirScan.GetName()); + rc = false; + } + } else if (strncmp(dirScan.GetName(), "incorrect.", 10) == 0) { + if (TestIncorrect("parsetest", dirScan.GetName())) { + LOG(info, "'%s' : negative test PASSED", dirScan.GetName()); + } else { + LOG(error, "'%s' : negative test FAILED", dirScan.GetName()); + rc = false; + } + } + } + return (rc ? 0 : 1); +} + + +int +main(int argc, char **argv) +{ + MyApp myapp; + return myapp.Entry(argc, argv); +} diff --git a/searchsummary/src/tests/docsumformat/dotest.sh b/searchsummary/src/tests/docsumformat/dotest.sh new file mode 100755 index 00000000000..64097b0061d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/dotest.sh @@ -0,0 +1,13 @@ +#!/bin/sh +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +echo "running pack test..." +./docsum-pack > packtest.out 2>&1 +res=$? +if [ $res -eq 0 ]; then + echo "pack test PASSED" +else + echo "pack test FAILED!" + echo "please check packtest.out" + exit 1 +fi diff --git a/searchsummary/src/tests/docsumformat/parsetest/.gitignore b/searchsummary/src/tests/docsumformat/parsetest/.gitignore new file mode 100644 index 00000000000..19815d313ff --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/.gitignore @@ -0,0 +1,2 @@ +*.out +out.* diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.1 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.1 new file mode 100644 index 00000000000..8238b53f81c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.1 @@ -0,0 +1,17 @@ +idtype none + +class default id 0 +field URL type string +field TITLE type string +field TEASER type string +field DSHOST type integer +field DSKEY type integer +field BYTES type integer +field WORDS type integer +field MODDATE type integer +field CRAWLDATE type integer +field LANG1 type byte +field LANG2 type byte +field LANG3 type byte +field LANG4 type byte +field CHARSET type integer diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.2 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.2 new file mode 100644 index 00000000000..8996c2dac4c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.2 @@ -0,0 +1,14 @@ +idtype byte + +class document id 1 +field title type string +field teaser type string +field url type string +field date type integer + +class image id 2 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.3 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.3 new file mode 100644 index 00000000000..ae29fa40335 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.3 @@ -0,0 +1,5 @@ +idtype none + +class default id 0 +field TITLE type string +field DATE type integer diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.4 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.4 new file mode 100644 index 00000000000..8238b53f81c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.4 @@ -0,0 +1,17 @@ +idtype none + +class default id 0 +field URL type string +field TITLE type string +field TEASER type string +field DSHOST type integer +field DSKEY type integer +field BYTES type integer +field WORDS type integer +field MODDATE type integer +field CRAWLDATE type integer +field LANG1 type byte +field LANG2 type byte +field LANG3 type byte +field LANG4 type byte +field CHARSET type integer diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.5 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.5 new file mode 100644 index 00000000000..6b6dc874a68 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.5 @@ -0,0 +1,3 @@ +idtype byte + +class myclass id 42 diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.6 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.6 new file mode 100644 index 00000000000..38416fdf45e --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.6 @@ -0,0 +1,5 @@ +idtype none + +class default id 0 +field TEASER type longstring +field DOCTEXT type longdata diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.7 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.7 new file mode 100644 index 00000000000..d1f17d25141 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.7 @@ -0,0 +1,11 @@ +idtype short + +class class_1 id 1 +field title type string +field rawteaser type data +field doctext type longdata +field dynteaser type longstring + +class class_2 id 2 +field title type string +field rawteaser type longdata diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.8 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.8 new file mode 100644 index 00000000000..e929b872a05 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.8 @@ -0,0 +1,7 @@ +idtype integer + +class class_50 id 50 +field title type data + +class class_100 id 100 +field title type string diff --git a/searchsummary/src/tests/docsumformat/parsetest/OK.correct.9 b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.9 new file mode 100644 index 00000000000..668505be77d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/OK.correct.9 @@ -0,0 +1,13 @@ +idtype none + +class default id 0 +field f0 type integer +field f1 type short +field f2 type byte +field f3 type float +field f4 type double +field f5 type int64 +field f6 type string +field f7 type data +field f8 type longstring +field f9 type longdata diff --git a/searchsummary/src/tests/docsumformat/parsetest/README b/searchsummary/src/tests/docsumformat/parsetest/README new file mode 100644 index 00000000000..2de83e1b0cb --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/README @@ -0,0 +1,24 @@ +The files in this directory are used to test the parsing of document +summary format config files. The files are named by the following +rules: + +incorrect.* : these files are incorrect; loading them should fail. + +correct.* : these files are correct; loading them should succeed. + +OK.correct.* : these files contain normalized config on 'summary.cf' + format that matches the config contained in + the corresponding 'correct.*' files. + +The 'docsum-parse' program loops through all files in this +directory. For each file that has a name beginning with 'incorrect.', +it checks that loading document summary format config from it +fails. For each file that has a name beginning with 'correct.', it +checks that document summary format config may be read from the +file. It then writes the config back to a file named 'out.correct.<>', +reads the newly generated file back in, reads the corresponding +'OK.correct.<>' file and checks that all 3 configs are exactly the +same. + +New tests may be added simply be adding files conforming to the above +rules to this directory. diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.1 b/searchsummary/src/tests/docsumformat/parsetest/correct.1 new file mode 100644 index 00000000000..0b3d57b7f9c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.1 @@ -0,0 +1,14 @@ +STRING URL +STRING TITLE +STRING TEASER +INT DSHOST +INT DSKEY +INT BYTES +INT WORDS +INT MODDATE +INT CRAWLDATE +BYTE LANG1 +BYTE LANG2 +BYTE LANG3 +BYTE LANG4 +INT CHARSET diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.2 b/searchsummary/src/tests/docsumformat/parsetest/correct.2 new file mode 100644 index 00000000000..8996c2dac4c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.2 @@ -0,0 +1,14 @@ +idtype byte + +class document id 1 +field title type string +field teaser type string +field url type string +field date type integer + +class image id 2 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.3 b/searchsummary/src/tests/docsumformat/parsetest/correct.3 new file mode 100644 index 00000000000..8a16e3f3fd1 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.3 @@ -0,0 +1,3 @@ +idtype byte +STRING TITLE +INT DATE diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.4 b/searchsummary/src/tests/docsumformat/parsetest/correct.4 new file mode 100644 index 00000000000..8238b53f81c --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.4 @@ -0,0 +1,17 @@ +idtype none + +class default id 0 +field URL type string +field TITLE type string +field TEASER type string +field DSHOST type integer +field DSKEY type integer +field BYTES type integer +field WORDS type integer +field MODDATE type integer +field CRAWLDATE type integer +field LANG1 type byte +field LANG2 type byte +field LANG3 type byte +field LANG4 type byte +field CHARSET type integer diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.5 b/searchsummary/src/tests/docsumformat/parsetest/correct.5 new file mode 100644 index 00000000000..d179537e208 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.5 @@ -0,0 +1,4 @@ +idtype byte +class myclass id 42 +STRING TITLE +INT DATE diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.6 b/searchsummary/src/tests/docsumformat/parsetest/correct.6 new file mode 100644 index 00000000000..a4e41ec72d8 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.6 @@ -0,0 +1,2 @@ +LONGSTRING TEASER +LONGDATA DOCTEXT diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.7 b/searchsummary/src/tests/docsumformat/parsetest/correct.7 new file mode 100644 index 00000000000..d1f17d25141 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.7 @@ -0,0 +1,11 @@ +idtype short + +class class_1 id 1 +field title type string +field rawteaser type data +field doctext type longdata +field dynteaser type longstring + +class class_2 id 2 +field title type string +field rawteaser type longdata diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.8 b/searchsummary/src/tests/docsumformat/parsetest/correct.8 new file mode 100644 index 00000000000..e929b872a05 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.8 @@ -0,0 +1,7 @@ +idtype integer + +class class_50 id 50 +field title type data + +class class_100 id 100 +field title type string diff --git a/searchsummary/src/tests/docsumformat/parsetest/correct.9 b/searchsummary/src/tests/docsumformat/parsetest/correct.9 new file mode 100644 index 00000000000..668505be77d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/correct.9 @@ -0,0 +1,13 @@ +idtype none + +class default id 0 +field f0 type integer +field f1 type short +field f2 type byte +field f3 type float +field f4 type double +field f5 type int64 +field f6 type string +field f7 type data +field f8 type longstring +field f9 type longdata diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.1 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.1 new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.1 diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.2 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.2 new file mode 100644 index 00000000000..600380f898d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.2 @@ -0,0 +1,14 @@ +idtype int + +class document id 1 +field title type string +field teaser type string +field url type string +field date type integer + +class image id 2 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.3 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.3 new file mode 100644 index 00000000000..35d46b73f96 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.3 @@ -0,0 +1,14 @@ +idtype byte + +class document id 1 +field title type string +field teaser type string +field url type string +field date type integer + +class image id 1 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.4 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.4 new file mode 100644 index 00000000000..f50c143b4be --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.4 @@ -0,0 +1,14 @@ +idtype byte + +class document id 1 +field title type string +field teaser type string +field url type string +field date type int + +class image id 2 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.5 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.5 new file mode 100644 index 00000000000..6579c30a29d --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.5 @@ -0,0 +1,14 @@ +idtype byte + +class document id 1 +field title type string +field teaser type string +field url type string +field url type integer + +class image id 2 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.6 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.6 new file mode 100644 index 00000000000..2ce1ab9507e --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.6 @@ -0,0 +1,13 @@ +idtype byte + +field title type string +field teaser type string +field url type string +field date type integer + +class image id 2 +field title type string +field date type integer +field width type short +field height type short +field bitmaps type byte diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.7 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.7 new file mode 100644 index 00000000000..e51bb1d2d48 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.7 @@ -0,0 +1,14 @@ +STRING URL +STRING TITLE +STRING TITLE +INT DSHOST +INT DSKEY +INT BYTES +INT WORDS +INT MODDATE +INT CRAWLDATE +BYTE LANG1 +BYTE LANG2 +BYTE LANG3 +BYTE LANG4 +INT CHARSET diff --git a/searchsummary/src/tests/docsumformat/parsetest/incorrect.8 b/searchsummary/src/tests/docsumformat/parsetest/incorrect.8 new file mode 100644 index 00000000000..7639557b734 --- /dev/null +++ b/searchsummary/src/tests/docsumformat/parsetest/incorrect.8 @@ -0,0 +1,2 @@ +idtype byte +STRING TITLE diff --git a/searchsummary/src/tests/docsummary/.gitignore b/searchsummary/src/tests/docsummary/.gitignore new file mode 100644 index 00000000000..3f0be20ca74 --- /dev/null +++ b/searchsummary/src/tests/docsummary/.gitignore @@ -0,0 +1,4 @@ +*_test +.depend +Makefile +searchsummary_positionsdfw_test_app diff --git a/searchsummary/src/tests/docsummary/CMakeLists.txt b/searchsummary/src/tests/docsummary/CMakeLists.txt new file mode 100644 index 00000000000..7eaa78d923e --- /dev/null +++ b/searchsummary/src/tests/docsummary/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchsummary_positionsdfw_test_app + SOURCES + positionsdfw_test.cpp + DEPENDS + searchsummary +) +vespa_add_test(NAME searchsummary_positionsdfw_test_app COMMAND searchsummary_positionsdfw_test_app) diff --git a/searchsummary/src/tests/docsummary/positionsdfw_test.cpp b/searchsummary/src/tests/docsummary/positionsdfw_test.cpp new file mode 100644 index 00000000000..59f91e12ef7 --- /dev/null +++ b/searchsummary/src/tests/docsummary/positionsdfw_test.cpp @@ -0,0 +1,142 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Unit tests for positionsdfw. + +#include <vespa/fastos/fastos.h> +#include <vespa/log/log.h> +LOG_SETUP("positionsdfw_test"); + +#include <vespa/searchlib/attribute/extendableattributes.h> +#include <vespa/searchlib/attribute/iattributemanager.h> +#include <vespa/searchsummary/docsummary/docsumfieldwriter.h> +#include <vespa/searchsummary/docsummary/positionsdfw.h> +#include <vespa/searchlib/util/rawbuf.h> +#include <vespa/vespalib/testkit/testapp.h> + +using search::RawBuf; +using search::IAttributeManager; +using search::SingleInt64ExtAttribute; +using search::attribute::IAttributeContext; +using search::attribute::IAttributeVector; +using vespalib::string; +using std::vector; + +namespace search { +namespace docsummary { + +namespace { + +class Test : public vespalib::TestApp { + void requireThat2DPositionFieldIsWritten(); + +public: + int Main(); +}; + +int +Test::Main() +{ + TEST_INIT("positionsdfw_test"); + + TEST_DO(requireThat2DPositionFieldIsWritten()); + + TEST_DONE(); +} + +struct MyEnvironment : IDocsumEnvironment { + IAttributeManager *attribute_man; + + MyEnvironment() : attribute_man(0) {} + + virtual IAttributeManager *getAttributeManager() { return attribute_man; } + virtual string lookupIndex(const string &s) const { return s; } + virtual juniper::Juniper *getJuniper() { return 0; } +}; + +class MyAttributeContext : public IAttributeContext { + const IAttributeVector &_attr; +public: + MyAttributeContext(const IAttributeVector &attr) : _attr(attr) {} + virtual const IAttributeVector *getAttribute(const string &) const { + return &_attr; + } + virtual const IAttributeVector *getAttributeStableEnum( + const string &) const { abort(); } + virtual void getAttributeList(vector<const IAttributeVector *> &) const + { abort(); } +}; + +class MyAttributeManager : public IAttributeManager { + const IAttributeVector &_attr; +public: + + MyAttributeManager(const IAttributeVector &attr) : _attr(attr) {} + virtual AttributeGuard::UP getAttribute(const string &) const { + abort(); + } + virtual AttributeGuard::UP getAttributeStableEnum(const string &) const { + abort(); + } + virtual void getAttributeList(vector<AttributeGuard> &) const { + abort(); + } + virtual IAttributeContext::UP createContext() const { + return IAttributeContext::UP(new MyAttributeContext(_attr)); + } +}; + +struct MyGetDocsumsStateCallback : GetDocsumsStateCallback { + virtual void FillSummaryFeatures(GetDocsumsState *, IDocsumEnvironment *) {} + virtual void FillRankFeatures(GetDocsumsState *, IDocsumEnvironment *) {} + virtual void ParseLocation(GetDocsumsState *) {} +}; + +template <typename AttrType> +void checkWritePositionField(Test &test, AttrType &attr, + uint32_t doc_id, const string &expected) { + for (AttributeVector::DocId i = 0; i < doc_id + 1; ) { + attr.addDoc(i); + if (i == 007) { + attr.add((int64_t) -1); + } else if (i == 0x42) { + attr.add(0xAAAAaaaaAAAAaaaa); + } else if (i == 0x17) { + attr.add(0x5555aaaa5555aaab); + } else if (i == 42) { + attr.add(0x8000000000000000); + } else { + attr.add(i); // value = docid + } + } + + MyAttributeManager attribute_man(attr); + PositionsDFW::UP writer = + createPositionsDFW(attr.getName().c_str(), &attribute_man); + ASSERT_TRUE(writer.get()); + ResType res_type = RES_LONG_STRING; + RawBuf target(1024); + MyGetDocsumsStateCallback callback; + GetDocsumsState state(callback); + state._attributes.push_back(&attr); + + writer->WriteField(doc_id, 0, &state, res_type, &target); + + test.EXPECT_EQUAL(expected.size(), *(const uint32_t *)(target.GetDrainPos())); + const char *p = target.GetDrainPos() + 4; + test.EXPECT_EQUAL(expected, string(p, p + expected.size())); +} + +void Test::requireThat2DPositionFieldIsWritten() { + SingleInt64ExtAttribute attr("foo"); + checkWritePositionField(*this, attr, 0x3e, "<position x=\"6\" y=\"7\" latlong=\"N0.000007;E0.000006\" />"); + checkWritePositionField(*this, attr, 007, "<position x=\"-1\" y=\"-1\" latlong=\"S0.000001;W0.000001\" />"); + checkWritePositionField(*this, attr, 0x42, "<position x=\"0\" y=\"-1\" latlong=\"S0.000001;E0.000000\" />"); + checkWritePositionField(*this, attr, 0x17, "<position x=\"-16711935\" y=\"16711935\" latlong=\"N16.711935;W16.711935\" />"); + checkWritePositionField(*this, attr, 42, ""); + +} + +} // namespace +} // namespace docsummary +} // namespace search + +TEST_APPHOOK(search::docsummary::Test); diff --git a/searchsummary/src/tests/docsummary/slime_summary/.gitignore b/searchsummary/src/tests/docsummary/slime_summary/.gitignore new file mode 100644 index 00000000000..1df864db333 --- /dev/null +++ b/searchsummary/src/tests/docsummary/slime_summary/.gitignore @@ -0,0 +1 @@ +searchsummary_slime_summary_test_app diff --git a/searchsummary/src/tests/docsummary/slime_summary/CMakeLists.txt b/searchsummary/src/tests/docsummary/slime_summary/CMakeLists.txt new file mode 100644 index 00000000000..a2bd3bbc610 --- /dev/null +++ b/searchsummary/src/tests/docsummary/slime_summary/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchsummary_slime_summary_test_app + SOURCES + slime_summary_test.cpp + DEPENDS + searchsummary +) +vespa_add_test(NAME searchsummary_slime_summary_test_app COMMAND searchsummary_slime_summary_test_app) diff --git a/searchsummary/src/tests/docsummary/slime_summary/FILES b/searchsummary/src/tests/docsummary/slime_summary/FILES new file mode 100644 index 00000000000..6d3a81d3ffc --- /dev/null +++ b/searchsummary/src/tests/docsummary/slime_summary/FILES @@ -0,0 +1 @@ +slime_summary_test.cpp diff --git a/searchsummary/src/tests/docsummary/slime_summary/slime_summary_test.cpp b/searchsummary/src/tests/docsummary/slime_summary/slime_summary_test.cpp new file mode 100644 index 00000000000..6509491d0ac --- /dev/null +++ b/searchsummary/src/tests/docsummary/slime_summary/slime_summary_test.cpp @@ -0,0 +1,125 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +#include <vespa/vespalib/testkit/test_kit.h> +#include <vespa/searchsummary/docsummary/docsumwriter.h> +#include <vespa/searchsummary/docsummary/resultpacker.h> +#include <vespa/searchlib/util/rawbuf.h> +#include <vespa/vespalib/data/slime/slime.h> +#include <vespa/vespalib/data/slime/simple_buffer.h> +#include <vespa/vespalib/data/slime/json_format.h> +#include <vespa/vespalib/data/slime/binary_format.h> +#include <vespa/searchlib/util/slime_output_raw_buf_adapter.h> + +using namespace vespalib::slime::convenience; +using namespace search::docsummary; + +namespace { + +struct FieldBlock { + Slime slime; + search::RawBuf binary; + + explicit FieldBlock(const vespalib::string &jsonInput) + : slime(), binary(1024) + { + size_t used = vespalib::slime::JsonFormat::decode(jsonInput, slime); + EXPECT_EQUAL(jsonInput.size(), used); + search::SlimeOutputRawBufAdapter adapter(binary); + vespalib::slime::BinaryFormat::encode(slime, adapter); + } + const char *data() const { return binary.GetDrainPos(); } + size_t dataLen() const { return binary.GetUsedLen(); } +}; + +struct DocsumFixture : IDocsumStore, GetDocsumsStateCallback { + std::unique_ptr<DynamicDocsumWriter> writer; + std::unique_ptr<ResultPacker> packer; + GetDocsumsState state; + DocsumFixture() : writer(), packer(), state(*this) { + ResultConfig *config = new ResultConfig(); + ResultClass *cfg = config->AddResultClass("default", 0); + EXPECT_TRUE(cfg != 0); + EXPECT_TRUE(cfg->AddConfigEntry("int_field", RES_INT)); + EXPECT_TRUE(cfg->AddConfigEntry("short_field", RES_SHORT)); + EXPECT_TRUE(cfg->AddConfigEntry("byte_field", RES_BYTE)); + EXPECT_TRUE(cfg->AddConfigEntry("float_field", RES_FLOAT)); + EXPECT_TRUE(cfg->AddConfigEntry("double_field", RES_DOUBLE)); + EXPECT_TRUE(cfg->AddConfigEntry("int64_field", RES_INT64)); + EXPECT_TRUE(cfg->AddConfigEntry("string_field", RES_STRING)); + EXPECT_TRUE(cfg->AddConfigEntry("data_field", RES_DATA)); + EXPECT_TRUE(cfg->AddConfigEntry("longstring_field", RES_LONG_STRING)); + EXPECT_TRUE(cfg->AddConfigEntry("longdata_field", RES_LONG_DATA)); + EXPECT_TRUE(cfg->AddConfigEntry("xmlstring_field", RES_XMLSTRING)); + EXPECT_TRUE(cfg->AddConfigEntry("jsonstring_field", RES_JSONSTRING)); + EXPECT_TRUE(cfg->AddConfigEntry("bad_jsonstring_field", RES_JSONSTRING)); + config->CreateEnumMaps(); + writer.reset(new DynamicDocsumWriter(config, 0)); + packer.reset(new ResultPacker(writer->GetResultConfig())); + state._args.setFlags(search::fs4transport::GDFLAG_ALLOW_SLIME); + } + void getDocsum(Slime &slime) { + uint32_t classId; + search::RawBuf buf(4096); + writer->WriteDocsum(1u, &state, this, &buf); + ASSERT_GREATER(buf.GetUsedLen(), sizeof(classId)); + memcpy(&classId, buf.GetDrainPos(), sizeof(classId)); + buf.Drain(sizeof(classId)); + EXPECT_EQUAL(classId, ::search::fs4transport::SLIME_MAGIC_ID); + EXPECT_GREATER(vespalib::slime::BinaryFormat + ::decode(Memory(buf.GetDrainPos(), buf.GetUsedLen()), slime), 0u); + } + virtual uint32_t getNumDocs() { return 2; } + virtual DocsumStoreValue getMappedDocsum(uint32_t docid, bool useSlimeInsideFields) { + EXPECT_EQUAL(true, useSlimeInsideFields); + EXPECT_EQUAL(1u, docid); + EXPECT_TRUE(packer->Init(0)); + EXPECT_TRUE(packer->AddInteger(4)); + EXPECT_TRUE(packer->AddShort(2)); + EXPECT_TRUE(packer->AddByte(1)); + EXPECT_TRUE(packer->AddFloat(4.5)); + EXPECT_TRUE(packer->AddDouble(8.75)); + EXPECT_TRUE(packer->AddInt64(8)); + EXPECT_TRUE(packer->AddString( "string", + strlen("string"))); + EXPECT_TRUE(packer->AddData( "data", + strlen("data"))); + EXPECT_TRUE(packer->AddLongString( "long_string", + strlen("long_string"))); + EXPECT_TRUE(packer->AddLongData( "long_data", + strlen("long_data"))); + EXPECT_TRUE(packer->AddLongString( "xml_string", + strlen("xml_string"))); + FieldBlock jsf1("{foo:1, bar:2}"); + EXPECT_TRUE(packer->AddLongData(jsf1.data(), jsf1.dataLen())); + EXPECT_TRUE(packer->AddLongString("abc", 3)); + const char *buf; + uint32_t len; + EXPECT_TRUE(packer->GetDocsumBlob(&buf, &len)); + return DocsumStoreValue(buf, len); + } + uint32_t getSummaryClassId() const override { return 0; } + virtual void FillSummaryFeatures(GetDocsumsState *, IDocsumEnvironment *) {} + virtual void FillRankFeatures(GetDocsumsState *, IDocsumEnvironment *) {} + virtual void ParseLocation(GetDocsumsState *) {} +}; + +} // namespace <unnamed> + +TEST_FF("require that docsum can be written as slime", DocsumFixture(), Slime()) { + f1.getDocsum(f2); + EXPECT_EQUAL(f2.get()["int_field"].asLong(), 4u); + EXPECT_EQUAL(f2.get()["short_field"].asLong(), 2u); + EXPECT_EQUAL(f2.get()["byte_field"].asLong(), 1u); + EXPECT_EQUAL(f2.get()["float_field"].asDouble(), 4.5); + EXPECT_EQUAL(f2.get()["double_field"].asDouble(), 8.75); + EXPECT_EQUAL(f2.get()["int64_field"].asLong(), 8u); + EXPECT_EQUAL(f2.get()["string_field"].asString().make_string(), std::string("string")); + EXPECT_EQUAL(f2.get()["data_field"].asData().make_string(), std::string("data")); + EXPECT_EQUAL(f2.get()["longstring_field"].asString().make_string(), std::string("long_string")); + EXPECT_EQUAL(f2.get()["longdata_field"].asData().make_string(), std::string("long_data")); + EXPECT_EQUAL(f2.get()["xmlstring_field"].asString().make_string(), std::string("xml_string")); + EXPECT_EQUAL(f2.get()["jsonstring_field"]["foo"].asLong(), 1u); + EXPECT_EQUAL(f2.get()["jsonstring_field"]["bar"].asLong(), 2u); + EXPECT_EQUAL(f2.get()["bad_jsonstring_field"].type().getId(), 0u); +} + +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/searchsummary/src/tests/extractkeywords/.gitignore b/searchsummary/src/tests/extractkeywords/.gitignore new file mode 100644 index 00000000000..1b50b24b284 --- /dev/null +++ b/searchsummary/src/tests/extractkeywords/.gitignore @@ -0,0 +1,7 @@ +*.core +.depend +Makefile +core +core.* +extractkeywordstest +searchsummary_extractkeywordstest_app diff --git a/searchsummary/src/tests/extractkeywords/CMakeLists.txt b/searchsummary/src/tests/extractkeywords/CMakeLists.txt new file mode 100644 index 00000000000..d726ffe794c --- /dev/null +++ b/searchsummary/src/tests/extractkeywords/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +vespa_add_executable(searchsummary_extractkeywordstest_app + SOURCES + extractkeywordstest.cpp + DEPENDS + searchsummary +) +vespa_add_test(NAME searchsummary_extractkeywordstest_app COMMAND sh runtests.sh) diff --git a/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp b/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp new file mode 100644 index 00000000000..59d949f40ca --- /dev/null +++ b/searchsummary/src/tests/extractkeywords/extractkeywordstest.cpp @@ -0,0 +1,295 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright (C) 2001-2003 Fast Search & Transfer ASA +// Copyright (C) 2003 Overture Services Norway AS + +#include <vespa/fastos/fastos.h> +#include <vespa/searchsummary/docsummary/keywordextractor.h> +#include <vespa/searchlib/parsequery/simplequerystack.h> +#include <vespa/searchlib/util/rawbuf.h> +#include "extractkeywordstest.h" + +#define NUMTESTS 5 + +int +ExtractKeywordsTest::Main() +{ + int doTest[NUMTESTS]; + int low, high, accnum, num; + int indicator; + bool verify = false; + int multiplier = 1; + bool failed = false; + + if (_argc == 1) + Usage(_argv[0]); + + // default initialize to not run any tests. + for (int n = 0; n < NUMTESTS; n++) + doTest[n] = 0; + + // parse the command line arguments + for (int i = 1; i < _argc; i++) { + low = 0; + high = NUMTESTS - 1; + char *p = _argv[i]; + + // Check if a multiplier is specified + if (*p == '*') { + p++; + accnum = 0; + while (*p != '\0') { + num = *p - '0'; + accnum = accnum * 10 + num; + p++; + } + multiplier = accnum; + continue; + } + + // Default is to run the tests specified, unless the first char is '/' + indicator = 1; + if (*p == '/') { + p++; + indicator = 0; + } + + // Find the first number + accnum = 0; + while (*p != '-' && *p != '\0') { + num = *p - '0'; + accnum = accnum * 10 + num; + p++; + } + if (accnum >= NUMTESTS) + continue; + low = accnum; + // Check for range operator + if (*p == '-') { + p++; + // Find the second number + accnum = 0; + while (*p != '\0') { + num = *p - '0'; + accnum = accnum * 10 + num; + p++; + } + if (accnum > 0) + high = accnum < NUMTESTS ? accnum : NUMTESTS-1; + } else + high = low; + + // Indicate the runrequest for the desired range. + for (int j = low; j <= high; j++) + doTest[j] = indicator; + } + + // Remove unused tests. + // doTest[1] = 0; + + // Remember time + if (multiplier > 1) { + printf("Running all tests %d times.\n", multiplier); + verify = false; + } else { + verify = true; + } + + int testCnt = 0; + + // init keyword extractor + _extractor = new search::docsummary::KeywordExtractor(NULL); + _extractor->AddLegalIndexSpec("*"); + + FastOS_Time timer; + timer.SetNow(); + + // Actually run the tests that we wanted. + for (int j = 0; j < multiplier; j++) + for (int k = 0; k < NUMTESTS; k++) + if (doTest[k] == 1) { + if (!RunTest(k, verify)) + failed = true; + testCnt++; + } + + // Print time taken + double timeTaken = timer.MilliSecsToNow(); + + printf("Time taken : %f ms\n", timeTaken); + printf("Number of tests run: %d\n", testCnt); + double avgTestPrMSec = static_cast<double>(testCnt) / timeTaken; + printf("Tests pr Sec: %f\n", avgTestPrMSec * 1000.0); + + delete _extractor; + _extractor = NULL; + + return failed ? 1 : 0; +} + +bool +ExtractKeywordsTest::ShowResult(int testNo, + const char *actual, const char *correct) +{ + const char *act_word = actual; + const char *cor_word = correct; + printf("%03d: ", testNo); + + while (*act_word != '\0') { + if (strcmp(act_word, cor_word) != 0) { + printf("fail. Keywords differ for act: %s, corr: %s\n", + act_word, cor_word); + return false; + } else { + act_word += strlen(act_word) + 1; + cor_word += strlen(cor_word) + 1; + } + } + if (*cor_word != '\0') { + printf("fail. actual list shorter than correct at %s\n", cor_word); + return false; + } + printf("ok\n"); + return true; +} + +/** + * + * @param testno The test to run. + * @param verify Verify the result of the test. + */ +bool +ExtractKeywordsTest::RunTest(int testno, bool verify) +{ + search::SimpleQueryStack stack; + search::RawBuf buf(32768); + const char *correct = NULL; + const char *keywords = NULL; + + switch (testno) { + case 0: + { + // Simple term query + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); + + stack.AppendBuffer(&buf); + keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); + correct = "foobar\0\0"; + + if (verify) ShowResult(testno, keywords, correct); + free(const_cast<char *>(keywords)); + break; + } + + case 1: + { + // multi term query + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_OR, 3)); + + stack.AppendBuffer(&buf); + keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); + correct = "bar\0foo\0foobar\0\0"; + + if (verify) ShowResult(testno, keywords, correct); + free(const_cast<char *>(keywords)); + break; + } + + case 2: + { + // phrase term query + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3)); + + stack.AppendBuffer(&buf); + keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); + correct = "bar foo foobar\0\0"; + + if (verify) ShowResult(testno, keywords, correct); + free(const_cast<char *>(keywords)); + break; + } + + case 3: + { + // multiple phrase and term query + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "xyzzy")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "xyz")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 2)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 3)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "baz")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "zog")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_AND, 3)); + + stack.AppendBuffer(&buf); + keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); + correct = "zog\0baz\0bar foo foobar\0xyz xyzzy\0\0"; + + if (verify) ShowResult(testno, keywords, correct); + free(const_cast<char *>(keywords)); + break; + } + + case 4: + { + // phrase term query with wrong argument items + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foobar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "foo")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_AND, 2)); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_TERM, "bar")); + stack.Push(new search::ParseItem(search::ParseItem::ITEM_PHRASE, 2)); + + stack.AppendBuffer(&buf); + keywords = _extractor->ExtractKeywords(vespalib::stringref(buf.GetDrainPos(), buf.GetUsedLen())); + correct = "\0"; + + if (verify) ShowResult(testno, keywords, correct); + free(const_cast<char *>(keywords)); + break; + } + + default: + { + printf("%03d: no such test\n", testno); + return false; + } + } + + bool result = true; + /* + if (verify) { + result = ShowResult(testno, pq->GetStack(), correct); + delete correct; + } else { + result = true; + } + delete pq; + */ + return result; +} + +void +ExtractKeywordsTest::Usage(char *progname) +{ + printf("%s {testnospec}+\n\ + Where testnospec is:\n\ + num: single test\n\ + num-num: inclusive range (open range permitted)\n",progname); + printf("There are tests from %d to %d\n\n", 0, NUMTESTS-1); + exit(-1); +} + +int +main(int argc, char** argv) +{ + ExtractKeywordsTest tester; + return tester.Entry(argc, argv); +} + diff --git a/searchsummary/src/tests/extractkeywords/extractkeywordstest.h b/searchsummary/src/tests/extractkeywords/extractkeywordstest.h new file mode 100644 index 00000000000..1a037fcb9cd --- /dev/null +++ b/searchsummary/src/tests/extractkeywords/extractkeywordstest.h @@ -0,0 +1,34 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Copyright (C) 2001-2003 Fast Search & Transfer ASA +// Copyright (C) 2003 Overture Services Norway AS + +#pragma once + +#include <vespa/fastos/fastos.h> + +namespace search { +namespace docummary { +class KeywordExtractor; +} +} + +class ExtractKeywordsTest : public FastOS_Application +{ +private: + ExtractKeywordsTest(const ExtractKeywordsTest &); + ExtractKeywordsTest& operator=(const ExtractKeywordsTest &); + + search::docsummary::KeywordExtractor *_extractor; + + int Main(); + void Usage(char *progname); + bool ShowResult(int testNo, const char *actual, const char *correct); + bool RunTest(int i, bool verify); + +public: + ExtractKeywordsTest(void) + : _extractor(NULL) + { + } +}; + diff --git a/searchsummary/src/tests/extractkeywords/runtests.sh b/searchsummary/src/tests/extractkeywords/runtests.sh new file mode 100755 index 00000000000..2c09bb25460 --- /dev/null +++ b/searchsummary/src/tests/extractkeywords/runtests.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +# +# $Id$ +# +# Copyright (C) 2000-2003 Fast Search & Transfer ASA +# Copyright (C) 2003 Overture Services Norway AS +# +# All Rights Reserved +# + +if $VALGRIND ./searchsummary_extractkeywordstest_app - +then + : +else + echo FAILED: searchsummary_extractkeywordstest_app test failed + exit 1 +fi + +if $VALGRIND ./searchsummary_extractkeywordstest_app - '*1000' +then + : +else + echo FAILED: searchsummary_extractkeywordstest_app test failed + exit 1 +fi + +echo SUCCESS: searchsummary_extractkeywordstest_app test completed +exit 0 diff --git a/searchsummary/src/tests/extractkeywords/testowner.ATS b/searchsummary/src/tests/extractkeywords/testowner.ATS new file mode 100644 index 00000000000..6d03b0836a4 --- /dev/null +++ b/searchsummary/src/tests/extractkeywords/testowner.ATS @@ -0,0 +1 @@ +vlarsen |