// unit-тесты (меняются в зависимости от версии программы)
#ifndef TEST_H
#define TEST_H
#include <cCommonSettings.h>
// external libraries
#include <windows.h>
#include <windowsx.h>
#include <wchar.h>
#include <string>
#include <sstream>
#include <iostream>
#include <locale>
#include <iomanip>
#include <tinyxml.h>
// internal libraries
#include <cUtil.h>
#include <cTextUtil.h>
#include <cClassUtil.h>
#include <cFile.h>
#include <cLogFile.h>
#include <cTable.h>
#include <txtstream.h>
#include <txtfstream.h>
#include <cRandomGenerator.h>
#include <cTree.h>
#include <cQPCounter.h>
#include <cArc.h>
#include <cComplexClassFactory.h> // список фабрик объектов классов
#include <cTableFactory.h> // отдельная фабрика объектов класса
#include <cMsgQueue.h>
#include <cThread.h>
using namespace std;
using namespace ns_log;
// вспомогательная для записи в таблицу, T = cBLOB
template<typename T>
bool fillrecord(ns_sc::record_ref record, const int& i, const float& f, const wstring& s, const T& b, const double& d, const uli& ul, const sli& sl)
{
// очистить запись
for (record_data::iterator r_it = record.begin();r_it != record.end();r_it++)
{
// от итератора к индексу, чтобы вычислить тип поля
index_value index = std::distance(record.begin(), r_it);
// по типу данных поля удаляем динамические значения полей
switch (index)
{
case 0 : { delete(static_cast<int*>(*r_it)); break; };
case 1 : { delete(static_cast<float*>(*r_it)); break; };
case 2 : { delete(static_cast<wstring*>(*r_it)); break; };
case 3 : { b.Erase(r_it); break; };
case 4 : { delete(static_cast<double*>(*r_it)); break; };
case 5 : { delete(static_cast<uli*>(*r_it)); break; };
case 6 : { delete(static_cast<sli*>(*r_it)); break; };
};
};
// удаляем указатели
record.erase(record.begin(), record.end());
record.push_back(new int(i));
record.push_back(new float(f));
record.push_back(new wstring(s));
T* pBLOB = new (T)(b);
const T& rBLOB = *pBLOB;
record.push_back(pBLOB);
record.push_back(new double(d));
record.push_back(new uli(ul));
record.push_back(new sli(sl));
return true;
};
// тестовый BLOB-класс с методами обработки
class cBLOB
{
protected:
int x,y;
public:
inline cBLOB() : x(10), y(20) {};
inline cBLOB(int _x, int _y) : x(_x), y(_y) {};
inline cBLOB(const cBLOB& BLOB) : x(BLOB.x), y(BLOB.y) {};
inline ~cBLOB() {};
inline int getx () const { return this->x; };
inline int gety () const { return this->y; };
inline static void* Append(void* pData)
{
cBLOB* tmpBLOB;
if (0 != pData)
tmpBLOB = new cBLOB(*(static_cast<cBLOB*>(pData)));
else
tmpBLOB = new cBLOB();
return tmpBLOB;
};
inline static bool Update(ns_sc::field_data_it it , void* pData)
{
cBLOB* pBLOBSrc = static_cast<cBLOB*>(pData);
cBLOB* pBLOBDst = static_cast<cBLOB*>(*it);
*pBLOBDst = *pBLOBSrc;
return true;
};
inline static bool Erase(ns_sc::field_data_it it) { cBLOB* pBLOB = static_cast<cBLOB*>(*it); delete pBLOB; *it = 0; return true; };
inline static uli Hash(ns_sc::field_data_it it) { cBLOB* pBLOB = static_cast<cBLOB*>(*it); return (pBLOB->x + pBLOB->y); };
inline static void Clear(ns_sc::field_data_it it)
{
cBLOB* pBLOB = static_cast<cBLOB*>(*it);
pBLOB->x = 0;
pBLOB->y = 0;
return;
};
};
// вспомогательная для вывода записи в лог, T = cBLOB
template<typename T>
bool sendrecord(ns_sc::record_ref Record, cLogFile& log)
{
log << L" (int) " << (*static_cast<int*>(Record[0]));
log << L" (float) " << ns_log::setprecision(6) << ns_log::fixed << (*static_cast<float*>(Record[1]));
log << L" (wstring) " << (*static_cast<wstring*>(Record[2]));
cBLOB& tmpBLOB = *static_cast<T*>(Record[3]);
log << L" (blob) x=" << tmpBLOB.getx() << L" y=" << tmpBLOB.gety();
log << L" (double) " << ns_log::setprecision(6) << ns_log::fixed << (*static_cast<double*>(Record[4])) << ns_log::endl;
log << L" (uli) " << (*static_cast<uli*>(Record[5]));
log << L" (sli) " << (*static_cast<sli*>(Record[6]));
return true;
};
inline int UnitTest()
{
// глобальная локаль приложения - локаль ОС
locale::global(locale(""));
// локаль для работы с текстом
const std::locale& rus = locale("ru_RU");
// пути к файлам
string path = "";
// лог
wstring Log = L"log\\Unittest.log";
// UTF-8
string utf8write = path + "log\\utf8write.txt";
string utf8read = path + "data\\utf8read.txt";
// UTF-16LE
string utf16write = path + "log\\utf16write.txt";
string utf16read = path + "data\\utf16read.txt";
// архив
wstring arcfile = L"log\\Unittest.pha";
// если через файл - форматирование вывода чисел слетает
// fixed(), setprecision() (причина внутри дебрей файлового потока в двоичном режиме)
//cLogFile* plog = cLogFile::instance(Log, cLogFile::ltFile);
cLogFile* plog = cLogFile::instance(Log, cLogFile::ltBuffer);
cLogFile& log = *plog;
if (0 == plog)
{
cout << "Unable to create log-file!" << endl;
return 1;
}
sli i (ns_sc::DEFSLI);
uli u (ns_sc::DEFULI);
float f(ns_sc::DEFFLOAT);
double d(ns_sc::DEFDOUBLE);
wstring s(ns_sc::DEFSTR);
log << L"Тестирование классов программы v1.0" << ns_log::endl << L"используется ббка STLPort v5.2";
log << ns_log::br << L"Список тестов:" << ns_log::endl << ns_log::endl;
log << L"- Примитивы для построения программы:" << ns_log::endl;
#define ENUMTEST
log << L"-- именованные константы (enum)" << ns_log::endl;
#define BITSETTEST
log << L"-- набор битовых флагов (bitset)" << ns_log::endl;
#define HASHTEST
log << L"-- вычисление хэш-функций (hash)" << ns_log::endl;
#define TABLETEST
log << L"-- таблица-справочник (table)" << ns_log::endl;
#define LCTEST
log << L"-- преобразование типов (lexical cast)" << ns_log::endl;
#define STRCMPTEST
log << L"-- сравнение строк" << ns_log::endl;
#define TXTWSTEST
log << L"-- поток текстовых данных (txt_wstringstream)" << ns_log::endl;
#define WIOFSTEST
#define TXTWOFSTEST
log << L"-- файловые потоки чтения/записи UCS2/UTF8 данных (wifstream/wofstream)" << ns_log::endl;
#define XMLTINYTEST
log << L"-- чтение и запись XML (tinyxml)" << ns_log::endl;
#define ARCTEST
log << L"-- классы чтения и записи pha-архивов (cPacker - cUnpacker)" << ns_log::endl;
#define JPGSTEST
log << L"-- поток чтения и записи jpg (jpg_stream)" << ns_log::endl;
#define JPGFSTEST
log << L"-- файловый поток чтения и записи jpg (jpg_fstream)" << ns_log::endl;
#define PNGSTEST
log << L"-- поток чтения и записи png (png_stream)" << ns_log::endl;
#define PNGFSTEST
log << L"-- файловый поток чтения и записи png (png_fstream)" << ns_log::endl;
#define BMPSTEST
log << L"-- поток чтения и записи bmp (bmp_stream)" << ns_log::endl;
#define BMPFSTEST
log << L"-- файловый поток чтения и записи bmp (bmp_fstream)" << ns_log::endl;
#define OGGSTEST
log << L"-- поток чтения и записи ogg (ogg_stream)" << ns_log::endl;
#define OGGFSTEST
log << L"-- файловый поток чтения и записи ogg (ogg_fstream)" << ns_log::endl;
#define WAVSTEST
log << L"-- поток чтения и записи wav (wav_stream)" << ns_log::endl;
#define WAVFSTEST
log << L"-- файловый поток чтения и записи wav (wav_fstream)" << ns_log::endl;
#define TREETEST
log << L"-- дерево объектов (tree)" << ns_log::endl;
#define OBJECTFACTORY
log << L"-- фабрика классов (classfactory)" << ns_log::endl;
#define MSGQUEUE
log << L"-- очередь сообщений (msgqueue)" << ns_log::endl;
#define THREADTEST
log << L"-- управление потоками (pthread)" << ns_log::endl;
{
#ifndef ENUMTEST
log << ns_log::br << L"#Тест отключен -- именованные константы (enum)" << ns_log::endl;
#else
log << ns_log::br << L"-- именованные константы (enum)" << ns_log::endl;
log << ns_log::endl << L"Дни недели:" << ns_log::endl;
typedef ns_wd::cWD::const_iterator enum_it;
for (enum_it it = ns_wd::WD.begin(); it != ns_wd::WD.end(); it++)
{
if (ns_sc::EOL != it->first)
log << L"ключ: " << it->first << L", значение: " << it->second << ns_log::endl;
};
#endif
}
{
#ifndef BITSETTEST
log << ns_log::br << L"#Тест отключен -- набор битовых флагов (bitset)" << ns_log::endl;
#else
log << ns_log::br << L"-- набор битовых флагов (bitset)" << ns_log::endl << ns_log::endl;
cBitset Bitset(255);
log << L"Начальный набор битов: " << Bitset.Get() << ns_log::endl;
for (uli i = 0; i < 32; i++)
{
log << L"Полное чтение битов до изменений, бит " << i << L": " << Bitset[i] << ns_log::endl;
};
log << ns_log::endl;
for (uli i = 0; i < 32; i++)
{
Bitset.Down(i);
log << L"После сброса бита " << i << L": " << Bitset.Get() << ns_log::endl;
Bitset.Up(i);
log << L"После установки бита " << i << L": " << Bitset.Get() << ns_log::endl;
};
log << ns_log::endl;
for (uli i = 0; i < 32; i++)
{
log << L"Полное чтение битов после изменений, бит " << i << L": " << Bitset[i] << ns_log::endl;
};
#endif
}
{
#ifndef HASHTEST
log << ns_log::br << L"#Тест отключен -- вычисление хэш-функций (hash)" << ns_log::endl;
#else
log << ns_log::br << L"-- вычисление хэш-функций (hash)" << ns_log::endl << ns_log::endl;
uli_vector uv;
uv.reserve(10);
uv.push_back(1);
uv.push_back(2);
uv.push_back(3);
uv.push_back(4);
uv.push_back(5);
uv.push_back(6);
uv.push_back(7);
uv.push_back(8);
uv.push_back(9);
uv.push_back(10);
log << L"хэш списка чисел (1-10) :: " << ulihash(uv, 0) << ns_log::endl;
uv[5] = 500;
log << L"хэш списка чисел (1-10, где 5е число заменено на 500) :: " << ulihash(uv, 0) << ns_log::endl;
log << ns_log::endl;
log << L"хэш строк:" << endl;
wstring sA = L"А роза упала на лапу Азора ";
wstring sB = L"А роза упала на лапу Азора!";
wstring sC = L"А роза упала на лапу азора ";
log << L"Первая строка: " << sA << L" ::" << strhash(sA) << ns_log::endl;
log << L"Вторая строка: " << sB << L" ::" << strhash(sB) << ns_log::endl;
log << L"Третья строка: " << sC << L" ::" << strhash(sC) << ns_log::endl;
#endif
}
{
#ifndef TABLETEST
log << ns_log::br << L"#Тест отключен -- таблица-справочник (table)" << ns_log::endl;
#else
log << ns_log::br << L"-- таблица-справочник (table)" << ns_log::endl << ns_log::endl;
log << L"Создание таблицы:" << ns_log::endl;
// имя таблицы,
// с использованием хэш-поиска (не только последовательного),
// ограничений на число хэш-таблиц нет
ns_tb::cTable Table(L"example_table");
log << L"Имя таблицы (name): " << Table.name() << ns_log::endl;
log << L"Исходное число записей таблицы (size): " << Table.size() << ns_log::endl;
log << (Table.empty() ? L"Таблица пуста (empty)" : L"Таблица не пуста (empty)") << ns_log::endl;
// заглушка под методы обработки объекта BLOB в таблице
sBLOBMethods BLOBMethods;
BLOBMethods.BLOBAppend = 0;
BLOBMethods.BLOBUpdate = 0;
BLOBMethods.BLOBErase = 0;
BLOBMethods.BLOBHash = 0;
// буфер полей таблицы
ns_tb::cField Field(L"",ns_tbe::BLOB, true, BLOBMethods);
typedef ns_tbe::cTBE::const_iterator tbe_it;
tbe_it fieldname_it;
const wstring CFieldOk = L"Поле добавлено: ";
const wstring UFieldOk = L"Поле изменено: ";
const wstring DFieldOk = L"Поле удалено: ";
const wstring CFieldEr = L"Поле в ключе и таблица не пуста, либо поле с данным именем уже существует: ";
const wstring UFieldEr = L"Поле в ключе, либо поля с данным именем не существует: ";
const wstring DFieldEr = L"Поле в ключе, либо поля с данным именем не существует: ";
log << ns_log::endl << L"Добавление полей таблицы:" << ns_log::endl;
fieldname_it = ns_tbe::TBE.find(ns_tbe::INT);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::INT);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << CFieldOk << Field.getname() << ns_log::endl) : (log << CFieldEr << Field.getname() << ns_log::endl);
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::FLOAT);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::FLOAT);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << CFieldOk << Field.getname() << ns_log::endl) : (log << CFieldEr << Field.getname() << ns_log::endl);
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::DOUBLE);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::DOUBLE);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << CFieldOk << Field.getname() << ns_log::endl) : (log << CFieldEr << Field.getname() << ns_log::endl);
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::STR);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::STR);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << CFieldOk << Field.getname() << ns_log::endl) : (log << CFieldEr << Field.getname() << ns_log::endl);
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::BLOB);
if (fieldname_it != ns_tbe::TBE.end())
{
// для BLOB-поля нужен особый конструктор
BLOBMethods.BLOBAppend = cBLOB::Append;
BLOBMethods.BLOBUpdate = cBLOB::Update;
BLOBMethods.BLOBErase = cBLOB::Erase;
BLOBMethods.BLOBHash = cBLOB::Hash;
ns_tb::cField Field(L"",ns_tbe::BLOB, true, BLOBMethods);
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::BLOB);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << CFieldOk << Field.getname() << ns_log::endl) : (log << CFieldEr << Field.getname() << ns_log::endl);
};
log << ns_log::endl << L"Добавление поля таблицы (FLOAT - дубликат):" << ns_log::endl;
fieldname_it = ns_tbe::TBE.find(ns_tbe::FLOAT);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::FLOAT);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << CFieldOk << Field.getname() << ns_log::endl) : (log << CFieldEr << Field.getname() << ns_log::endl);
};
log << ns_log::endl << L"Изменение поля таблицы (FLOAT):" << ns_log::endl;
// ищем
fieldname_it = ns_tbe::TBE.find(ns_tbe::FLOAT);
if (fieldname_it != ns_tbe::TBE.end())
{
(Table.getfieldinfo(L"FLOAT", Field)) ? log << L"Поле в ключе: " << Field.getkey() << L" " : log << L"Поле не найдено! ";
Field.setname(L"FLOAT");
Field.settype(ns_tbe::FLOAT);
Field.setkey(false);
// обновление метаданных поля
if (Table.updatefield(Field))
{
(Table.getfieldinfo(L"FLOAT", Field)) ? log << UFieldOk : log << UFieldEr;
}
else
log << UFieldEr << L"#" << Field.getname() << ns_log::endl;
(Table.getfieldinfo(L"FLOAT", Field)) ? log << L"Поле в ключе: " : log << L"Поле не найдено!";
log << Field.getkey() << ns_log::endl;
// ищем указатель на тип данных поля
fieldname_it = ns_tbe::TBE.find(Field.gettype());
if (fieldname_it != ns_tbe::TBE.end())
log << L"Тип данных поля: " << fieldname_it->second << ns_log::endl;
else
log << L"Тип данных поля неизвестен! " << ns_log::endl;
};
log << ns_log::endl << L"Cписок полей таблицы (" << Table.getfieldcount() << L") после изменения:" << ns_log::endl;
for(uli index = 0; index < Table.getfieldcount(); index++)
{
if (Table.getfieldinfo(index, Field))
log << Field.getname() << L" тип: " << Field.gettype() << ns_log::endl;
};
log << ns_log::endl << L"Удаляем поле таблицы! " << ns_log::endl;
// ищем указатель на поле типа DOUBLE
fieldname_it = ns_tbe::TBE.find(ns_tbe::DOUBLE);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
(Table.erasefield(Field)) ? (log << DFieldOk << Field.getname() << ns_log::endl) : (log << DFieldEr << Field.getname() << ns_log::endl);
};
log << ns_log::endl << L"Cписок полей таблицы (" << Table.getfieldcount() << L") после удаления поля:" << ns_log::endl;
for(uli index = 0; index < Table.getfieldcount(); index++)
{
if (Table.getfieldinfo(index, Field))
log << Field.getname() << L" тип: " << Field.gettype() << ns_log::endl;
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::DOUBLE);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::DOUBLE);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << ns_log::endl << CFieldOk << Field.getname() << ns_log::endl) : (log << ns_log::endl << CFieldEr << Field.getname() << ns_log::endl);
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::ULI);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::ULI);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << ns_log::endl << CFieldOk << Field.getname() << ns_log::endl) : (log << ns_log::endl << CFieldEr << Field.getname() << ns_log::endl);
};
fieldname_it = ns_tbe::TBE.find(ns_tbe::SLI);
if (fieldname_it != ns_tbe::TBE.end())
{
Field.setname(fieldname_it->second);
Field.settype(ns_tbe::SLI);
Field.setkey(true);
(Table.appendfield(Field)) ? (log << ns_log::endl << CFieldOk << Field.getname() << ns_log::endl) : (log << ns_log::endl << CFieldEr << Field.getname() << ns_log::endl);
};
log << ns_log::endl << L"Cписок полей таблицы (" << Table.getfieldcount() << L") после добавления поля:" << ns_log::endl;
for(uli index = 0; index < Table.getfieldcount(); index++)
{
if (Table.getfieldinfo(index, Field))
log << Field.getname() << L" (тип " << Field.gettype() << L")" << ns_log::endl;
};
log << ns_log::endl;
// добавляем индексы
// ПК
if (Table.createindex())
log << ns_log::endl << L"ПК создан успешно" << ns_log::endl;
else
log << ns_log::endl << L"ПК создать не удалось" << ns_log::endl;
// формируем структуру записи
ns_sc::record_data Record;
log << ns_log::endl << L"Всего должно быть успешно добавлено записей: 3" << ns_log::endl;
// запись 1
// специально добавляем объект в поле таблицы
cBLOB* pBLOB1 = new cBLOB(5, 5);
cBLOB& BLOB1 = *pBLOB1;
log << L"добавляем запись 1: ";
fillrecord<cBLOB>(Record, 777, 56.78901f, L"\"Строка записи таблицы\"", BLOB1, 56.78901, 241, -333);
Table.appendrecord(Record) ? (log << L"Успешно" << ns_log::endl) : (log << L"Добавить не получилось - ошибка!" << ns_log::endl);
// запись 2
// операция не должна быть успешна
log << L"добавляем запись 2 (дубликат записи 1): ";
Table.appendrecord(Record) ? (log << L"Успешно" << ns_log::endl) : (log << L"Добавить не получилось - ошибка!" << ns_log::endl);
// запись 3
cBLOB* pBLOB2 = new cBLOB(8, 8);
cBLOB& BLOB2 = *pBLOB2;
log << L"добавляем запись 3 (BLOB изменен): ";
fillrecord<cBLOB>(Record, 777, 56.78901f, L"\"Строка записи таблицы\"", BLOB2, 56.78901, 241, -333);
Table.appendrecord(Record) ? (log << L"Успешно" << ns_log::endl) : (log << L"Добавить не получилось - ошибка!" << ns_log::endl);
// запись 4
cBLOB * pBLOB3 = new cBLOB(7, 7);
cBLOB& BLOB3 = *pBLOB3;
log << L"добавляем запись 4 (FLOAT изменен - не в ключе): ";
fillrecord<cBLOB>(Record, 777, 56.55555f, L"\"Строка записи таблицы\"", BLOB3, 56.78901, 241, -333);
Table.appendrecord(Record) ? (log << L"Успешно" << ns_log::endl) : (log << L"Добавить не получилось - ошибка!" << ns_log::endl);
// запись 5
log << L"добавляем запись 5 (дубликат записи 4): ";
Table.appendrecord(Record) ? (log << L"Успешно" << ns_log::endl) : (log << L"Добавить не получилось - ошибка!" << ns_log::endl);
log << ns_log::endl << L"Cписок ключевых полей таблицы (" << Table.getfieldcount() << L"):" << ns_log::endl;
for(uli index = 0; index < Table.getfieldcount(); index++)
{
if (Table.getfieldinfo(index, Field))
if (Field.getkey())
log << Field.getname() << ns_log::endl;
};
log << ns_log::endl << L"Cписок полей таблицы (" << Table.getfieldcount() << L"):" << ns_log::endl;
for(uli index = 0; index < Table.getfieldcount(); index++)
{
if (Table.getfieldinfo(index, Field))
log << Field.getname() << ns_log::endl;
};
// выводим записи:
log << ns_log::endl << L"Всего добавлено записей: " << Table.size();
log << ns_log::endl << L"Читаем таблицу последовательно:" << ns_log::endl << ns_log::endl;
for (uli i = 0; i < Table.size(); i++)
{
log << ns_log::endl << L"запись " << i << L"# ";
if (Table.getrecord(Record, i))
sendrecord<cBLOB>(Record, log);
};
// поиск записи по ключу:
log << ns_log::endl << L"Поиск записи по ключу " << Table.size();
log << ns_log::endl << L"Ищем запись : 777, 0.0f, \"Строка записи таблицы\", BLOB(8,8), 56.78901, 241, -333" << ns_log::endl;
// запись
cBLOB* pBLOB4 = new cBLOB(8, 8);
cBLOB& BLOB4 = *pBLOB4;
fillrecord<cBLOB>(Record, 777, 0.0f, L"\"Строка записи таблицы\"", BLOB4, 56.78901, 241, -333);
if (Table.findnext(Record))
{
log << L"Найдена запись:";
sendrecord<cBLOB>(Record, log);
};
#endif
}
{
#ifndef LCTEST
log << ns_log::br << L"#Тест отключен -- преобразование типов (lexical cast)" << ns_log::endl;
#else
log << ns_log::br << L"-- преобразование типов (lexical cast)" << ns_log::endl << ns_log::endl;
// переменные тестов
i = -100;
u = 100;
f = static_cast<float>(100.123456);
d = 100.123456;
s = L"Привет, мир!!!";
log << ns_log::endl << L"2STR: " << ns_log::endl << L"исходные переменные:" << ns_log::endl;
log << L"sli(-100): " << i << ns_log::endl;
log << L"uli(100): " << u << ns_log::endl;
log << L"float(100,123456): " << ns_log::fixed << ns_log::setprecision(6) << f << L" - Округляется!" << ns_log::endl;
log << L"double(100,123456): " << ns_log::fixed << ns_log::setprecision(6) << d << ns_log::endl;
log << ns_log::endl << L"в строку:" << ns_log::endl;
lc(&i,&s, ns_sc::DEFSTR); log << L"sli2str(-100): " << s << ns_log::endl;
lc(&u,&s, ns_sc::DEFSTR); log << L"uli2str(100): " << s << ns_log::endl;
lc(&f,&s, ns_sc::DEFSTR); log << L"float2str(100.123456): " << s << L" - Округляется!" << ns_log::endl;
lc(&d,&s, ns_sc::DEFSTR); log << L"double2str(100.123456): " << s << ns_log::endl;
log << endl << L"STR2: " << ns_log::endl << L"исходные переменные:" << ns_log::endl;
s = L"-888.123456";
log << L"str(-888.123456): " << s << ns_log::endl;
d = i = u = ns_sc::DEFULI;
f = static_cast<float>(ns_sc::DEFULI);
log << ns_log::endl << L"из строки:" << ns_log::endl;
lc(&s,&i, ns_sc::DEFSLI); log << L"str2sli: " << i << L" - дробная часть отбрасывается " << ns_log::endl;
lc(&s,&u, ns_sc::DEFULI); log << L"str2uli: " << u << L" - приходим к дополнению числа " << ns_log::endl;
lc(&s,&f, ns_sc::DEFFLOAT); log << L"str2float: " << ns_log::fixed << ns_log::setprecision(6) << f << L" - Округляется!" << ns_log::endl;
lc(&s,&d, ns_sc::DEFDOUBLE); log << L"str2double: " << ns_log::fixed << ns_log::setprecision(6) << d << ns_log::endl;
log << ns_log::endl << L"Вывод: использовать float крайне не рекомендуется!" << ns_log::endl;
log << ns_log::endl << L"PS. лог-файл не может дополнительно форматировать текст" << ns_log::endl
<< L"при открытии в бинарном режиме (число знаков после разделителя целой и дробной частей)!" << ns_log::endl;
#endif
}
{
#ifndef STRCMPTEST
log << ns_log::br << L"#Тест отключен -- сравнение строк" << ns_log::endl;
#else
log << ns_log::br << L"-- сравнение строк" << ns_log::endl << ns_log::endl;
wstring sA = L"А роза упала на лапу Азора";
wstring sB = L"А роза упала на лапу азора";
log << L"Первая строка: " << sA << ns_log::endl;
log << L"Вторая строка: " << sB << ns_log::endl;
log << L"Первая строка сравнивается сама с собой: " << ns_log::endl;
streq(sA, sA) ? log << L"Строки равны." << ns_log::endl : log << L"Строки не равны!" << ns_log::endl;
log << L"Первая строка сравнивается со второй: " << ns_log::endl;
streq(sA, sB) ? log << L"Строки равны." << ns_log::endl : log << L"Строки не равны!" << ns_log::endl;
sB = sA;
log << L"Вторая строка после перезаписи: " << sB << ns_log::endl;
log << L"Первая строка сравнивается со второй: " << ns_log::endl;
streq(sA, sB) ? log << L"Строки равны." << ns_log::endl : log << L"Строки не равны!" << ns_log::endl;
#endif
}
{
#ifndef TXTWSTEST
log << ns_log::br << L"#Тест отключен -- поток текстовых данных (txt_wstringstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- поток текстовых данных (txt_wstringstream)" << ns_log::endl;
const std::locale & il = std::locale();
const std::locale & ol = std::locale();
txt_wstringstream txt_container(il, ol);
// переменные тестов
i = -100;
u = 100;
f = static_cast<float>(100.123456);
d = 100.123456;
s = L"Привет, мир!!!";
log << ns_log::endl << L"исходные переменные:" << ns_log::endl;
log << L"sli(-100): " << i << ns_log::endl;
log << L"uli(100): " << u << ns_log::endl;
log << L"float(100,123456): " << ns_log::fixed << ns_log::setprecision(6) << f << L" - Округляется!" << ns_log::endl;
log << L"double(100,123456): " << ns_log::fixed << ns_log::setprecision(6) << d << ns_log::endl;
log << L"string(Привет, мир!!!): " << s << ns_log::endl;
// д.вызываться метод класса txt_wstringstream
txt_container << i << ns_txt::endl
<< u << ns_txt::endl
<< ns_txt::fixed << ns_txt::setprecision(6) << f << ns_txt::endl
<< ns_txt::fixed << ns_txt::setprecision(6) << d << ns_txt::endl
<< s << ns_txt::endl;
i = u = 0;
f = static_cast<float>(d = 0.0);
s = L"";
log << ns_log::endl << L"переменные из потока:" << ns_log::endl;
txt_container >> i
>> u
>> f
>> d
>> s;
log << L"sli(-100): " << i << ns_log::endl;
log << L"uli(100): " << u << ns_log::endl;
log << L"float(100,123456): " << ns_log::fixed << ns_log::setprecision(6) << f << L" - Округляется!" << ns_log::endl;
log << L"double(100,123456): " << ns_log::fixed << ns_log::setprecision(6) << d << ns_log::endl;
log << L"string(Привет, мир!!!): " << s << ns_log::endl;
log << ns_log::endl << L"список строк (тест) и вектор чисел (90-99) в поток и обратно:" << ns_log::endl;
// тестовые объекты
wstringstream test_str(L"");
for (uli i = 0; i < 5; i++) test_str << L"тест " << std::endl;
std::vector<wstring> test_v;
test_v.reserve(10);
for (uli i = 90; i < 100; i++)
{
lc(&i,&s, ns_sc::DEFSTR);
test_v.push_back(s);
};
// заполняем контейнер
txt_container << test_str << test_v;
// чистим объекты
test_str.str(L"");
test_v.clear();
test_v.reserve(10);
// читаем обратно
txt_container >> test_str >> test_v;
// вывод в лог
while (std::getline(test_str, s))
log << s << ns_log::endl;
for (uli i = 0; i != test_v.size(); i++)
{
log << test_v[i];
};
#endif
}
{
#ifndef WIOFSTEST
log << ns_log::br << L"#Тест отключен -- файловые потоки чтения/записи UCS2/UTF8 данных (wifstream/wofstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловые потоки чтения/записи UCS2/UTF8 данных (wifstream/wofstream)" << ns_log::endl;
wstring ws16(L"Dummy");
wstring ws8(L"Dummy");
string s8("Dummy");
// UTF-16LE из файла
ns_cvt::wifstream_ucs2* ifs = new ns_cvt::wifstream_ucs2(utf16read, std::ios_base::in, rus);
if (ifs->is_open())
{
getline((*ifs),ws16);
(*ifs).close();
};
delete ifs;
// UTF-8 из файла
ns_cvt::wifstream_utf8* ifs2 = new ns_cvt::wifstream_utf8(utf8read, std::ios_base::in, rus);
if (ifs2->is_open())
{
getline ((*ifs2),ws8);
(*ifs2).close();
};
delete ifs2;
// UTF-16LE в файл
wofstream_ucs2* ofs = new wofstream_ucs2(utf16write, std::ios_base::binary | std::ios_base::out, true, rus);
if (ofs->is_open())
{
// s8 = w2s(ws8);
// ns_cp::UTF8TOUCS2(s8, ws16);
(*ofs) << ws8;
(*ofs).close();
};
delete ofs;
// UTF-8 в файл
ns_cvt::wofstream_utf8* ofs2 = new ns_cvt::wofstream_utf8(utf8write.c_str(), std::ios_base::binary | std::ios_base::out, false, rus);
if (ofs2->is_open())
{
// ns_cp::UCS2TOUTF8(ws16, s8);
(*ofs2) << s2w(s8);
(*ofs2).close();
};
delete ofs2;
log << L"Итоги теста смотреть в файлах (log)" << ns_log::endl;
#endif
}
{
#ifndef TXTWOFSTEST
log << ns_log::br << L"#Тест отключен -- файловый поток записи текстовых данных (txt_wofstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловый поток записи текстовых данных (txt_wofstream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef XMLTINYTEST
log << ns_log::br << L"#Тест отключен -- чтение и запись XML (tinyxml)" << ns_log::endl;
#else
log << ns_log::br << L"-- чтение и запись XML (tinyxml)" << ns_log::endl;
// файл xml
TiXmlDocument doc( "etc\\ini.xml" );
if (!doc.LoadFile())
{
log << L"Невозможно открыть файл!" << ns_log::endl;
}
else
{
log << L"Файл успешно считан!" << ns_log::endl;
TiXmlDocument doc;
TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" );
doc.LinkEndChild( decl );
TiXmlElement * element = new TiXmlElement( "body" );
doc.LinkEndChild( element );
TiXmlText * text = new TiXmlText( "Привет, Мир" );
element->LinkEndChild( text );
if (!doc.SaveFile( "log\\ini_xml_copy.xml" ))
log << L"Невозможно сохранить файл!" << ns_log::endl;
else
log << L"Файл успешно сохранен!" << ns_log::endl;
};
#endif
}
{
#ifndef ARCTEST
log << ns_log::br << L"#Тест отключен -- классы чтения и записи pha-архивов (cPacker - cUnpacker)" << ns_log::endl;
#else
log << ns_log::br << L"-- классы чтения и записи pha-архивов (cPacker - cUnpacker)" << ns_log::endl;
log << ns_log::endl << L"Сжатие файла в архив (cPacker)" << ns_log::endl
<< L"(Путь к файлу добавляется в архив, образуя вложенные папки):" << ns_log::endl;
// прогресс упаковки показывать не будем, поэтому все параметры 0
ns_arc::cPacker Packer(0, 0);
ns_arc::sItem Item;
// ОБЯЗАТЕЛЬНО имя объекта/путь - ключевое поле идентификации объекта (хэш поля)
Item.UCS2Item = L"log\\ini_xml_copy.xml";
Item.UTF8Item = "log\\ini_xml_copy.xml";
Item.UTF8ItemSize = Item.UTF8Item.length();
Item.Type = 0;
Item.Path = ns_sc::DEFSTR; // ОБЯЗАТЕЛЬНО исходный объект не в архиве
Item.Ptr = 0; // ОБЯЗАТЕЛЬНО исходный объект не в ОЗУ
Item.Method.Id = ns_arc::ARLZMA;
Item.Method.Level = 9;
Item.AsIs = (0 == Item.Method.Level);
Item.Method.DictionarySize = 0;
Item.Method.WordSize = 0;
Item.Method.BlockSize = 0;
Item.SourceSize = 0;
Item.CompressedSize = 0;
Packer.add(Item);
bool res = Packer.pack(arcfile);
(res)?
log << L"Тест пройден успешно" << ns_log::endl :
log << L"Тест не пройден: " << res << ns_log::endl;
log << ns_log::endl << L"Разжатие архива в копию файла (cUnpacker):" << ns_log::endl;
// прогресс распаковки показывать не будем, поэтому все параметры 0
ns_arc::cUnpacker Unpacker(0, 0);
if (Unpacker.open(arcfile))
{
log << L"Архив открыт" << ns_log::endl;
// ищем описание объекта
// ОБЯЗАТЕЛЬНО полное имя - уже известно
if (Unpacker.getiteminfo(Item))
{
log << L"Информация о файле найдена" << ns_log::endl;
// ОБЯЗАТЕЛЬНО куда распаковать - в файл
Item.Path = Item.UCS2Item + L"_copy";
if (Unpacker.unpack(Item))
log << L"Тест пройден успешно" << ns_log::endl;
else
log << L"Распаковать файл не удалось" << ns_log::endl;
}
else
log << L"Файл в архиве не найден" << ns_log::endl;
}
else
log << L"Тест не пройден" << ns_log::endl;
#endif
}
{
#ifndef JPGSTEST
log << ns_log::br << L"#Тест отключен -- поток чтения и записи jpg (jpg_stream)" << ns_log::endl;
#else
log << ns_log::br << L"-- поток чтения и записи jpg (jpg_stream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef JPGFSTEST
log << ns_log::br << L"#Тест отключен -- файловый поток чтения и записи jpg (jpg_fstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловый поток чтения и записи jpg (jpg_fstream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef PNGSTEST
log << ns_log::br << L"#Тест отключен -- поток чтения и записи png (png_stream)" << ns_log::endl;
#else
log << ns_log::br << L"-- поток чтения и записи png (png_stream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef PNGFSTEST
log << ns_log::br << L"#Тест отключен -- файловый поток чтения и записи png (png_fstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловый поток чтения и записи png (png_fstream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef BMPSTEST
log << ns_log::br << L"#Тест отключен -- поток чтения и записи bmp (bmp_stream)" << ns_log::endl;
#else
log << ns_log::br << L"-- поток чтения и записи bmp (bmp_stream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef BMPFSTEST
log << ns_log::br << L"#Тест отключен -- файловый поток чтения и записи bmp (bmp_fstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловый поток чтения и записи bmp (bmp_fstream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef OGGSTEST
log << ns_log::br << L"#Тест отключен -- поток чтения и записи ogg (ogg_stream)" << ns_log::endl;
#else
log << ns_log::br << L"-- поток чтения и записи ogg (ogg_stream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef OGGFSTEST
log << ns_log::br << L"#Тест отключен -- файловый поток чтения и записи ogg (ogg_fstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловый поток чтения и записи ogg (ogg_fstream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef WAVSTEST
log << ns_log::br << L"#Тест отключен -- поток чтения и записи wav (wav_stream)" << ns_log::endl;
#else
log << ns_log::br << L"-- поток чтения и записи wav (wav_stream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef WAVFSTEST
log << ns_log::br << L"#Тест отключен -- файловый поток чтения и записи wav (wav_fstream)" << ns_log::endl;
#else
log << ns_log::br << L"-- файловый поток чтения и записи wav (wav_fstream)" << ns_log::endl;
log << L"Не реализовано!" << ns_log::endl;
#endif
}
{
#ifndef TREETEST
log << ns_log::br << L"#Тест отключен -- дерево объектов (tree)" << ns_log::endl;
#else
log << ns_log::br << L"-- дерево объектов (tree)" << ns_log::endl;
// методы работы с объектом ptr дерева - используем заглушку
sBLOBMethods ptrMethods = {ns_tree::ptrAppend, ns_tree::ptrUpdate, ns_tree::ptrErase, 0};
// методы работы с объектом датавремя дерева
sBLOBMethods tmMethods = {ns_tree::tmAppend, ns_tree::tmUpdate, ns_tree::tmErase, 0};
// дерево
ns_tree::cTree otree(ptrMethods, tmMethods);
// заполняем дерево - несколько объектов
// буфер узла дерева
ns_tree::cTreeNode node;
ns_tree::filltreenode(node,
1, // OUID
ns_tree::TOROOT, // parent
1, // CLASSUID
0, // level
L"дерево объектов (tree)", // name
0, // ptr
0, // size
ns_tree::TOROOT, // type
ns_arc::ARNO, // method
0, // from
0, // to
L"NOTE", // note
0, // lifetime
ptrMethods, // ptr methods (copy, update, erase)
tmMethods // datetime methods (copy, update, erase)
);
otree.append(node);
// ищем запись по всем индексам
for(uli index = 0; index < 10; index++)
{
if (otree.findnext(node, static_cast<ns_tree::eTreeIndex>(index)))
{
log << L"поиск по индексу " << (*(ns_tree::TI.find(index))).second << L" успешен! " << ns_log::endl;
};
};
node.id = 600;
if (!otree.findnext(node, ns_tree::TIID))
{
log << L"поиск по индексу несуществующего узла безуспешен!" << ns_log::endl;
};
log << ns_log::endl;
log << L"размер одного хранимого объекта дерева в байтах: " << static_cast<uli>(sizeof(ns_tree::cTreeNode)) << ns_log::endl;
log << L"размер одного хранимого объекта дерева в байтах: " << static_cast<uli>(sizeof(node)) << ns_log::endl;
log << L"размер uli в байтах: " << static_cast<uli>(sizeof(uli)) << ns_log::endl;
log << L"размер sli в байтах: " << static_cast<uli>(sizeof(sli)) << ns_log::endl;
log << L"размер tm* в байтах: " << static_cast<uli>(sizeof(pdatetime)) << ns_log::endl;
log << L"размер void* в байтах: " << static_cast<uli>(sizeof(void*)) << ns_log::endl;
log << L"размер wstring в байтах: " << static_cast<uli>(sizeof(node.name)) << ns_log::endl;
log << L"размер wstring в байтах: " << static_cast<uli>(sizeof(node.note)) << ns_log::endl;
#endif
}
{
#ifndef OBJECTFACTORY
log << ns_log::br << L"#Тест отключен -- фабрика классов (classfactory)" << ns_log::endl;
#else
log << ns_log::br << L"-- фабрика классов (classfactory)" << ns_log::endl;
// создаем фабрику классов (список фабрик объектов классов)
cComplexClassFactory * CCF = cComplexClassFactory::instance();
// указатель на фабрику одного класса
cTableFactory* pTF;
// инициализация фабрик объектов классов
log << ns_log::endl << L"Создаем фабрику отрядов первой армии" << ns_log::endl;
pTF = new cTableFactory(L"First Army", 10);
CCF->append(pTF);
log << L"Создаем фабрику отрядов второй армии" << ns_log::endl;
pTF = new cTableFactory(L"Second Army", 10);
CCF->append(pTF);
// создаем один объект через фабрику объектов класса
pTF = static_cast<cTableFactory*>(CCF->get(L"First Army"));
cTable* pTable = pTF->newobject(L"first army squad");
// использование объекта
log << ns_log::endl
<< L"имя первого отряда первой армии = " << pTable->name() << ns_log::endl
<< L"максимум отрядов второй армии: " << CCF->maxsize(L"Second Army") << ns_log::endl;
// удаление фабрик объектов обязательно
pTF = static_cast<cTableFactory*>(CCF->get(L"First Army"));
pTF->clear();
pTF = static_cast<cTableFactory*>(CCF->get(L"Second Army"));
pTF->clear();
// сами фабрики удалятся автоматом
cComplexClassFactory::freeinstance();
log << L"Тест пройден успешно" << ns_log::endl;
#endif
}
{
#ifndef MSGQUEUE
log << ns_log::br << L"#Тест отключен -- очередь сообщений (msgqueue)" << ns_log::endl;
#else
log << ns_log::br << L"-- очередь сообщений (msgqueue)" << ns_log::endl;
log << L"размер одного сообщения в байтах" << ns_log::endl
<< L"без учета доп.параметров (массива uli): " << static_cast<uli>(sizeof(ns_msg::sMsg)) << ns_log::endl;
log << L"очередь сообщений со статическим буфером в 1000 сообщений" << ns_log::endl;
ns_msg::cMsgQueue MsgQueue(1000);
log << L"размер буфера очереди в сообщениях: " << MsgQueue.size() << ns_log::endl;
log << L"количество несортированных сообщений в буфере: " << MsgQueue.unsortedsize() << ns_log::endl;
log << L"количество свободных сообщений в буфере после сортировки: " << MsgQueue.sort() << ns_log::endl;
ns_msg::sMsg msg;
// взаимодействие объектов (игровая логика) реализуется через очередь сообщений и через дерево объектов
// реакции объектов на взаимодействие (методы объектов) хранит очередь сообщений
// на каждой итерации игрового цикла делается перебор объектов дерева в указанном игрой порядке,
// и каждый объект отрабатывает сообщения, предназначенные ему, после чего генерирует новые сообщения
// свойства объектов, с которыми происходит взаимодействие, хранятся в дереве объектов
// методы объектов, (т.н, ИИ, игровая логика) могут быть реализованы скриптами,
// как последовательность отслеживаемых и генерируемых событий
// моделируем взаимодействие объектов тетриса
enum eTetrisMembers {TMGAME = 0, TMMENU, TMMOVIE, TMGLASS, TMFIGURE};
enum eTetrisMessage {TMWAIT = 0, /*ожидание следующей команды*/
TMMERGE, /*соединить фигуру со стаканом*/
TMDIE, /*уничтожить объект*/
TMINIT, /*инициализация объекта*/
TMGAMEOVER, /*конец игры*/
TMSHOWMOVIE /*проиграть заставку*/
};
log << L"вставка сообщений в буфер" << ns_log::endl;
// фигура упала в стакан - соединяем фигуру со стаканом
// фигура ждет сообщения стакана для продолжения реакции на события
ns_msg::setmsg(MsgQueue, TMGLASS, TMFIGURE, TMMERGE, ns_msg::MS1, new uli[4]); // id фигуры, x, y координаты и угол поворота
// стакан обновил состояние
// командует фигуре пересоздать фигуру и фигуру next
// стакан ждет следующего сообщения от фигуры или игры, остальные игнорируются
ns_msg::setmsg(MsgQueue, TMFIGURE, TMGLASS, TMINIT, ns_msg::MS1, 0);
// фигура не может быть пересоздана - сообщение о том, что игра окончена
// общему менеджеру игры
// стакан и фигура ждут следующего сообщения от игры, остальные игнорируются
ns_msg::setmsg(MsgQueue, TMGAME, TMFIGURE, TMGAMEOVER, ns_msg::MS1, 0);
// замораживаем фигуру и next, чтобы изображение оставалось, а других изменений объекта не происходило
// стакан и фигура ждут следующего сообщения от игры, остальные игнорируются
ns_msg::setmsg(MsgQueue, TMFIGURE, TMGAME, TMWAIT, ns_msg::MS1, 0);
// замораживаем стакан, чтобы изображение оставалось, а других изменений объекта не происходило
// стакан и фигура ждут следующего сообщения от игры, остальные игнорируются
ns_msg::setmsg(MsgQueue, TMGLASS, TMGAME, TMWAIT, ns_msg::MS1, 0);
// проиграть заставку GameOver поверх стакана
// - крутится с ожиданием сообщений от игры - она синхронизирует анимацию
// и анализирует сигналы от управления игрока
// (вместо очередного кадра будет прислано сообщение заморозить анимацию)
ns_msg::setmsg(MsgQueue, TMMOVIE, TMGAME, TMSHOWMOVIE, ns_msg::MS1, new uli[25]); // 1 uli - длина списка параметров, + 24 uli - id-ресурсов-изображений
log << L"после вставки: " << ns_log::endl;
log << L"размер буфера очереди в сообщениях: " << MsgQueue.size() << ns_log::endl;
log << L"количество несортированных сообщений в буфере: " << MsgQueue.unsortedsize() << ns_log::endl;
log << L"количество свободных сообщений в буфере после сортировки: " << MsgQueue.sort() << ns_log::endl;
log << L"количество несортированных сообщений в буфере: " << MsgQueue.unsortedsize() << ns_log::endl;
log << L"обрабатываем все сообщения" << ns_log::endl;
{ // обход дерева объектов в нужном порядке - эмуляция через for(;;);
uli counter = 1;
for (uli i = TMGAME; i <= TMFIGURE; i++)
{
switch (i)
{
case TMGAME:
if (ns_msg::getmsg(MsgQueue, msg, TMGAME, ns_msg::MSPROCESSED, SC.first, PM.update)) do
log << L"получатель = GAME, код сообщения = " << msg.message << L", помечаем на удаление" << ns_log::endl;
while (ns_msg::getmsg(MsgQueue, msg, TMGAME, ns_msg::MSPROCESSED, SC.next, PM.update)); break;
case TMMENU:
if (ns_msg::getmsg(MsgQueue, msg, TMMENU, ns_msg::MSPROCESSED, SC.first, PM.update)) do
log << L"получатель = MENU, код сообщения = " << msg.message << L", помечаем на удаление" << ns_log::endl;
while (ns_msg::getmsg(MsgQueue, msg, TMMENU, ns_msg::MSPROCESSED, SC.next, PM.update)); break;
case TMMOVIE:
while (counter < 24)
{
// не удаляем сообщение, но при этом оно единственное, вытаскиваем его 24 раза
if (ns_msg::getmsg(MsgQueue, msg, TMMOVIE, ns_msg::MSPROCESSED, SC.first, PM.noupdate))
{
log << L"получатель = MOVIE, код сообщения = " << msg.message << L", кадр " << counter << L" не удаляем" << ns_log::endl;
counter++;
}
else
counter = 24;
};
if (ns_msg::getmsg(MsgQueue, msg, TMMOVIE, ns_msg::MSPROCESSED, SC.first, PM.update))
log << L"получатель = MOVIE, код сообщения = " << msg.message << L", кадр " << counter << L" помечаем на удаление" << ns_log::endl;
break;
case TMGLASS:
if (ns_msg::getmsg(MsgQueue, msg, TMGLASS, ns_msg::MSPROCESSED, SC.first, PM.update)) do
log << L"получатель = GLASS, код сообщения = " << msg.message << L", помечаем на удаление" << ns_log::endl;
while (ns_msg::getmsg(MsgQueue, msg, TMGLASS, ns_msg::MSPROCESSED, SC.next, PM.update)); break;
case TMFIGURE:
if (ns_msg::getmsg(MsgQueue, msg, TMFIGURE, ns_msg::MSPROCESSED, SC.first, PM.update)) do
log << L"получатель = FIGURE, код сообщения = " << msg.message << L", помечаем на удаление" << ns_log::endl;
while (ns_msg::getmsg(MsgQueue, msg, TMFIGURE, ns_msg::MSPROCESSED, SC.next, PM.update)); break;
default: break;
};
};
// конец обхода дерева, упорядочиваем все необработанные сообщения очереди
log << L"после обработки сообщений: " << ns_log::endl;
log << L"размер буфера очереди в сообщениях: " << MsgQueue.size() << ns_log::endl;
log << L"количество несортированных сообщений в буфере: " << MsgQueue.unsortedsize() << ns_log::endl;
log << L"количество свободных сообщений в буфере после сортировки: " << MsgQueue.sort() << ns_log::endl;
log << L"количество несортированных сообщений в буфере: " << MsgQueue.unsortedsize() << ns_log::endl;
}
#endif
}
{
#ifndef THREADTEST
log << ns_log::br << L"#Тест отключен -- управление потоками (pthread)" << ns_log::endl;
#else
log << ns_log::br << L"-- управление потоками (pthread)" << ns_log::endl;
// cThread - создает и уничтожает нить
// cTimerThread - периодически задает нити работу, считая указанные интервалы времени
// cExampleThread - работа нити, заключается в выводе в консоль сообщения
ns_thread::cExampleThread* ExampleThread = new ns_thread::cExampleThread(ns_time::cpSec, 3);
// стартуем нить
ExampleThread->start();
// ждем 10 секунд, чтобы получить результат: ~3 сообщения в консоль
Sleep(10000);
// уничтожаем нить
ExampleThread->suspend();
// освобождаем память
delete ExampleThread;
#endif
}
log << ns_log::br;
log << L"Окончание всех тестов." << endl;
cLogFile::freeinstance();
return 0;
};
#endif // TEST_H