ultimatepp/uppsrc/TCore/datatest.cpp
rylek fa59ec7b80 DropList::Format patched to respect DisplayAll modifier; minor fixes in CalcType
git-svn-id: svn://ultimatepp.org/upp/trunk@1542 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2009-09-01 21:58:57 +00:00

672 lines
13 KiB
C++

#include "TCoreDb.h"
NAMESPACE_UPP
static String GetRandomString(int maxlength = 50000, int minlength = 0)
{
int len = minlength;
unsigned span = maxlength - minlength;
if(span > 0)
{
unsigned v = rand();
if(span >= RAND_MAX)
v += rand() * RAND_MAX;
len += rand() % (span + 1);
}
StringBuffer s(len);
for(int i = 0; i < len; i++)
s[i] = rand();
return s;
}
void DataFile::FileTest()
{
String name = ForceExt(GetTempFileName(), ".cdb");
DataFile file;
if(!file.Create(name))
{
RLOG("Cannot create file '" << name << "'.");
NEVER();
return;
}
enum
{
COUNT = 100,
OBJECTS = 1000,
LENGTH = 50000,
};
Vector<String> values;
srand(1);
int i;
for(i = 0; i < COUNT; i++)
{
int x = rand() % (int)OBJECTS;
String s = GetRandomString(LENGTH);
values.DoIndex(x) = s;
file.Set(x, s, 0);
}
file.Commit(0);
file.Compact();
for(i = 0; i < values.GetCount(); i++)
{
String from = file.Get(i);
if(from != values[i])
{
RLOG("DataFile::Set/Get mismatch at #" << i
<< " (" << from.GetLength() << " / " << values[i].GetLength() << ")");
NEVER();
}
}
file.Close();
DeleteFile(name);
}
void DataBase::AllocTest()
{
RLOG("DataBase::AllocTest");
String name = ForceExt(GetTempFileName(), ".cdb");
DataFile df;
if(!df.Create(name))
{
RLOG("Cannot create file '" << name << "'.");
NEVER();
return;
}
DataBase db;
int master = db.Create(df, 0);
Vector< Vector<Value> > rows;
{ // fill in table
DataTable& table = db.Add("POKUS");
table.AddColumn("A", STRING_V);
table.AddColumn("B", INT_V);
db.Commit();
df.Commit(0);
enum
{
COUNT = 1000,
OBJECTS = 1000,
};
srand(1);
for(int i = 0; i < COUNT; i++)
{
if(i % 10 == 0)
RDUMP(i);
int x = rand() % (int)OBJECTS;
if(rows.GetCount() > x && !rows[x].IsEmpty())
{ // empty / modify row
if(rand() & 1)
{
table.Remove(x);
rows[x].Clear();
}
else
{
Vector<Value>& row = rows[x];
row[0] = GetRandomString();
row[1] = rand();
table.Set(x, row);
}
}
else
{ // add row
Vector<Value> row;
row.Add(GetRandomString());
row.Add(rand());
x = table.Add(row);
rows.DoIndex(x) = row;
}
if((i & 15) == 0)
table.Commit();
}
}
db.Commit();
db.Close();
df.Compact();
db.Open(df, master, 0);
{ // check table
DataTable& table = db["POKUS"];
int i = rows.GetCount();
while(i && rows[i - 1].IsEmpty())
i--;
ASSERT(table.GetRowIndex().GetEndIndex() == i);
while(--i >= 0)
{
if(i % 10 == 0)
RDUMP(i);
VERIFY(rows[i].IsEmpty() == table.IsEmpty(i));
if(!rows[i].IsEmpty())
{
Vector<Value> row = table.Get(i);
VERIFY(row[0] == rows[i][0] && row[1] == rows[i][1]);
}
}
}
db.Close();
df.Close();
DeleteFile(name);
}
static Date anchor_date(2000, 1, 1);
enum { ROW_COUNT = 100000 };
static void CreateDataBase(const String& fn, int& aobj, int& bobj, int& cobj, int& dobj, int& eobj, int& fobj, int& iobj)
{
DataFile df;
#ifdef NO_CACHE
df.SetCache(16384, 50000, 50000);
#endif//NO_CACHE
if(!df.Create(fn))
{
RLOG("error creating file '" << fn << "'");
NEVER();
return;
}
DataColumnOf<int> a, b;
DataColumnOf<String> c;
DataColumnOf<Date> d;
DataColumnOf<Time> e;
DataColumnOf<bool> f;
DataRowIndex index;
#ifdef NO_CACHE
a.SetCacheSize(0);
b.SetCacheSize(0);
c.SetCacheSize(0);
d.SetCacheSize(0);
e.SetCacheSize(0);
f.SetCacheSize(0);
#endif//NO_CACHE
aobj = a.Create(df, 1);
bobj = b.Create(df, 2);
cobj = c.Create(df, 3);
dobj = d.Create(df, 4);
eobj = e.Create(df, 5);
fobj = f.Create(df, 6);
iobj = index.Create(df, 7);
/*
a.SetCount(COUNT);
b.SetCount(COUNT);
c.SetCount(COUNT);
d.SetCount(COUNT);
e.SetCount(COUNT);
*/
for(int i = 0; i < ROW_COUNT; i++)
{
if(i % 1000 == 0)
RLOG("Writing " << i);
// LOG("#" << i);
// if(i == 49001)
// __asm int 3
int x = index.Add();
a.Set(x, i);
b.Set(x, -i);
String vc = "ab" + IntStr(i) + "cd";
// if(i % 1000 == 0)
// vc.Cat('*', 10 * i);
c.Set(x, vc);
d.Set(x, anchor_date + i);
e.Set(x, ToTime(anchor_date) + i);
f.Set(x, i & 1);
}
a.Commit(); a.Close();
b.Commit(); b.Close();
c.Commit(); c.Close();
d.Commit(); d.Close();
e.Commit(); e.Close();
f.Commit(); f.Close();
index.Commit(); index.Close();
df.Commit(0);
df.Close();
}
static void CheckColumnA(DataFile& df, int aobj)
{
DataColumnOf<int> a;
a.Open(df, aobj, 1);
for(int i = 0; i < a.GetCount(); i++)
{
if((int)a[i] != i)
{
String s;
s << "Mismatch: a[" << i << "] = " << StdFormat(a[i]) << ", " << 3 * i << " expected";
RLOG(s);
NEVER();
}
a.Set(i, 3 * i);
}
a.Commit();
}
static void CheckColumnA2(DataFile& df, int aobj)
{
DataColumnOf<int> a;
a.Open(df, aobj, 1);
for(int i = 0; i < a.GetCount(); i++)
if((int)a[i] != 3 * i)
{
String s;
s << "Mismatch: a[" << i << "] = " << StdFormat(a[i]) << ", " << 3 * i << " expected";
RLOG(s);
NEVER();
}
}
static void CheckColumnB(DataFile& df, int bobj)
{
DataColumnOf<int> b;
b.Open(df, bobj, 2);
for(int i = 0; i < b.GetCount(); i++)
{
if((int)b[i] != -i)
{
String s;
s << "Mismatch: b[" << i << "] = " << StdFormat(b[i]) << ", " << -i << " expected";
RLOG(s);
NEVER();
}
b.Set(i, -i * i);
}
b.Commit();
}
static void CheckColumnB2(DataFile& df, int bobj)
{
DataColumnOf<int> b;
b.Open(df, bobj, 2);
for(int i = 0; i < b.GetCount(); i++)
if((int)b[i] != -i * i)
{
String s;
s << "Mismatch: b[" << i << "] = " << StdFormat(b[i]) << ", " << -i * i << " expected";
RLOG(s);
NEVER();
}
}
static void CheckColumnC(DataFile& df, int cobj)
{
DataColumnOf<String> c;
c.Open(df, cobj, 3);
for(int i = 0; i < c.GetCount(); i++)
{
// if(i == 179540)
// __asm int 3
String t = c[i], e = "ab" + IntStr(i) + "cd";
// if(i % 1000 == 0)
// e.Cat('*', 10 * i);
if(t != e)
{
String s;
s << "Mismatch: c[" << i << "] = " << StdFormat(c[i]) << ", " << e << " expected";
RLOG(s);
NEVER();
}
c.Set(i, "ab" + IntStr(i) + "cd_ef" + IntStr(-i));
}
c.Commit();
}
static void CheckColumnC2(DataFile& df, int cobj)
{
DataColumnOf<String> c;
c.Open(df, cobj, 3);
for(int i = 0; i < c.GetCount(); i++)
{
String t = c[i], e = "ab" + IntStr(i) + "cd_ef" + IntStr(-i);
if(t != e)
{
String s;
s << "Mismatch: c[" << i << "] = " << StdFormat(c[i]) << ", " << e << " expected";
RLOG(s);
NEVER();
}
}
}
static void CheckColumnD(DataFile& df, int dobj)
{
DataColumnOf<Date> d;
d.Open(df, dobj, 4);
for(int i = 0; i < d.GetCount(); i++)
{
if(Date(d[i]) != anchor_date + i)
{
String s;
s << "Mismatch: d[" << i << "] = " << StdFormat(d[i]) << ", " << Format(anchor_date + i) << " expected";
RLOG(s);
NEVER();
}
d.Set(i, anchor_date - 2 * i);
}
d.Commit();
}
static void CheckColumnD2(DataFile& df, int dobj)
{
DataColumnOf<Date> d;
d.Open(df, dobj, 4);
for(int i = 0; i < d.GetCount(); i++)
if(Date(d[i]) != anchor_date - 2 * i)
{
String s;
s << "Mismatch: d[" << i << "] = " << StdFormat(d[i])
<< ", " << Format(anchor_date - 2 * i) << " expected";
RLOG(s);
NEVER();
}
}
static void CheckColumnE(DataFile& df, int eobj)
{
DataColumnOf<Time> e;
e.Open(df, eobj, 5);
for(int i = 0; i < e.GetCount(); i++)
{
Time dest = ToTime(anchor_date) + i;
if(Time(e[i]) != dest)
{
String s;
s << "Mismatch: e[" << i << "] = " << StdFormat(e[i])
<< ", " << Format(dest) << " expected";
RLOG(s);
NEVER();
}
e.Set(i, ToTime(anchor_date) - 2 * i);
}
e.Commit();
}
static void CheckColumnE2(DataFile& df, int eobj)
{
DataColumnOf<Time> e;
e.Open(df, eobj, 5);
for(int i = 0; i < e.GetCount(); i++)
{
Time dest = ToTime(anchor_date) - 2 * i;
if(Time(e[i]) != dest)
{
String s;
s << "Mismatch: e[" << i << "] = " << StdFormat(e[i]) << ", "
<< Format(dest) << " expected";
RLOG(s);
NEVER();
}
}
}
static void CheckColumnF(DataFile& df, int fobj)
{
DataColumnOf<bool> f;
f.Open(df, fobj, 6);
for(int i = 0; i < ROW_COUNT; i++)
{
if(CalcType<bool>::ValueTo(f[i]) != bool(i & 1))
{
String s;
s << "Mismatch: f[" << i << "] = " << StdFormat(f[i]) << ", " << (i & 1) << " expected";
RLOG(s);
NEVER();
}
f.Set(i, CalcType<bool>::ToValue(i & 2));
}
f.Commit();
}
static void CheckColumnF2(DataFile& df, int fobj)
{
DataColumnOf<bool> f;
f.Open(df, fobj, 6);
for(int i = 0; i < ROW_COUNT; i++)
{
bool b = i & 2;
if(CalcType<bool>::ValueTo(f[i]) != b)
{
String s;
s << "Mismatch: f[" << i << "] = " << StdFormat(f[i]) << ", " << b << " expected";
RLOG(s);
NEVER();
}
}
}
static void CheckIndex(DataFile& df, int iobj)
{
DataRowIndex index;
index.Open(df, iobj, 6);
RLOG("Index count = " << index.GetCount() << ", first empty = "
<< index.GetFirstEmpty() << ", end index = " << index.GetEndIndex());
Index<int> to_remove;
srand(1);
int top = index.GetEndIndex();
int rem = top / 4;
to_remove.Reserve(rem);
while(to_remove.GetCount() < rem)
{
int r = rand() + rand() * RAND_MAX;
to_remove.FindAdd(r % top);
}
RLOG("Removing " << rem << " entries...");
index.Remove(to_remove.GetKeys());
int i;
for(i = 0; i < top; i++)
if(index.IsEmpty(i) != (to_remove.Find(i) >= 0))
{
NEVER();
}
RLOG("Index count = " << index.GetCount() << ", first empty = "
<< index.GetFirstEmpty() << ", end index = " << index.GetEndIndex());
RLOG("Reallocating items...");
Vector<int> sorted;
sorted <<= to_remove.GetKeys();
Sort(sorted);
for(i = 0; i < rem; i++)
{
int alloc = index.Add();
ASSERT(alloc == sorted[i]);
}
RLOG("Index count = " << index.GetCount() << ", first empty = "
<< index.GetFirstEmpty() << ", end index = " << index.GetEndIndex());
}
static void CheckDataBase(const String& fn, int aobj, int bobj, int cobj, int dobj, int eobj, int fobj, int iobj)
{
DataFile df;
df.SetCache(16384, 100000, 100000);
if(!df.Open(fn))
{
RLOG("error opening file '" << fn << "'");
NEVER();
return;
}
/*
{
String ex = AppendFileName(GetTempPath(), "pokus.cdi");
FileOut fo(ex);
if(!fo.IsOpen())
CmdError("error creating file '" + ex + "'");
df.Export(fo);
}
*/
/*
RLOG("Checking RowIndex...");
CheckIndex(df, iobj);
RLOG("Checking A...");
CheckColumnA(df, aobj);
RLOG("Checking B...");
CheckColumnB(df, bobj);
*/
RLOG("Checking C...");
CheckColumnC(df, cobj);
/*
RLOG("Checking D...");
CheckColumnD(df, dobj);
RLOG("Checking E...");
CheckColumnE(df, eobj);
RLOG("Checking F...");
CheckColumnF(df, fobj);
*/
df.Commit(0);
df.Close();
}
static void CheckDataBase2(const String& fn, int aobj, int bobj, int cobj, int dobj, int eobj, int fobj, int iobj)
{
DataFile df;
df.SetCache(16384, 100000, 100000);
if(!df.Open(fn))
{
RLOG("error opening file '" << fn << "'");
NEVER();
return;
}
// df.Commit(0);
RLOG("Database file size = " << df.GetFileSize() << ", overhead = " << df.GetOverhead() << "%");
RLOG("Compacting...\n");
// df.Compact();
RLOG("Database file size = " << df.GetFileSize() << ", overhead = " << df.GetOverhead() << "%");
/*
RLOG("Checking A/2...");
CheckColumnA2(df, aobj);
RLOG("Checking B/2...");
CheckColumnB2(df, bobj);
*/
RLOG("Checking C/2...");
CheckColumnC2(df, cobj);
/*
RLOG("Checking D/2...");
CheckColumnD2(df, dobj);
RLOG("Checking E/2...");
CheckColumnE2(df, eobj);
RLOG("Checking F/2...");
CheckColumnF2(df, fobj);
*/
df.Commit(0);
df.Close();
}
static void RawDataFileTest()
{
String fn = ForceExt(GetTempFileName(), ".cdb");
int aobj, bobj, cobj, dobj, eobj, fobj, iobj;
CreateDataBase(fn, aobj, bobj, cobj, dobj, eobj, fobj, iobj);
CheckDataBase(fn, aobj, bobj, cobj, dobj, eobj, fobj, iobj);
CheckDataBase2(fn, aobj, bobj, cobj, dobj, eobj, fobj, iobj);
DeleteFile(fn);
}
static void StructuredDataBaseTest(const String& fn)
{
DataFile df;
if(!df.Create(fn))
throw ObjectExc("cannot create file '" + fn + "'");
DataBase db;
int i = db.Create(df, 0);
if(i)
throw ObjectExc("database creation error");
DataTable& table = db.Add("TestTable");
table.AddColumn("ColumnInt", INT_V, DataTableColumn::NUMBER_INDEX);
table.AddColumn("ColumnDouble", DOUBLE_V);
table.AddColumn("ColumnString", STRING_V);
{
StringStream ss;
db.Describe(ss);
RLOG(ss.GetResult());
}
for(i = 0; i < 100000; i++)
{
if(i % 1000 == 0)
RLOG(i);
Vector<Value> v;
v << i << sin((double)i) << ("hello world " + IntStr(i));
table.Add(v);
}
{
StringStream ss;
db.Describe(ss);
RLOG(ss.GetResult());
}
{
DataSet items = table.Column(0).GetRange(50, 60);
VppLog() << "Range <50, 60>: ";
for(int i = 0; i < items.GetCount(); i++)
VppLog() << items[i] << ' ';
RLOG("");
}
{
double min, max;
table.Column(0).GetMinMax(min, max);
RLOG("MinMax(0) = <" << min << ", " << max << ">");
table.Column(1).GetMinMax(min, max);
RLOG("MinMax(1) = <" << min << ", " << max << ">");
}
db.Commit();
df.Commit(0);
}
static void DataBaseTest2(const String& fn)
{
DataFile df;
if(!df.Open(fn))
throw ObjectExc("cannot open file '" + fn + "'");
DataBase db;
db.Open(df, 0, 0);
StringStream ss;
db.Describe(ss);
RLOG(ss.GetResult());
}
void DataBase::ColumnTest()
{
RLOG("DataBase::ColumnTest");
RawDataFileTest();
}
void DataBase::StructuredTest()
{
String name = ForceExt(GetTempFileName(), ".cdb");
StructuredDataBaseTest(name);
DataBaseTest2(name);
DeleteFile(name);
}
void DataBase::FullTest()
{
DataFile::FileTest();
AllocTest();
ColumnTest();
StructuredTest();
}
END_UPP_NAMESPACE