aboutsummaryrefslogtreecommitdiffstats
path: root/searchsummary/src/tests/docsumformat
diff options
context:
space:
mode:
authorJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
committerJon Bratseth <bratseth@yahoo-inc.com>2016-06-15 23:09:44 +0200
commit72231250ed81e10d66bfe70701e64fa5fe50f712 (patch)
tree2728bba1131a6f6e5bdf95afec7d7ff9358dac50 /searchsummary/src/tests/docsumformat
Publish
Diffstat (limited to 'searchsummary/src/tests/docsumformat')
-rw-r--r--searchsummary/src/tests/docsumformat/.gitignore21
-rw-r--r--searchsummary/src/tests/docsumformat/CMakeLists.txt8
-rwxr-xr-xsearchsummary/src/tests/docsumformat/docsum-index.sh16
-rw-r--r--searchsummary/src/tests/docsumformat/docsum-pack.cpp631
-rw-r--r--searchsummary/src/tests/docsumformat/docsum-parse.cpp201
-rwxr-xr-xsearchsummary/src/tests/docsumformat/dotest.sh13
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/.gitignore2
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.117
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.214
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.35
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.417
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.53
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.65
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.711
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.87
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/OK.correct.913
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/README24
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.114
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.214
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.33
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.417
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.54
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.62
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.711
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.87
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/correct.913
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.10
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.214
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.314
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.414
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.514
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.613
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.714
-rw-r--r--searchsummary/src/tests/docsumformat/parsetest/incorrect.82
34 files changed, 1178 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