diff --git a/SessionChunkIO.h b/SessionChunkIO.h index af6b380..8df9110 100644 --- a/SessionChunkIO.h +++ b/SessionChunkIO.h @@ -16,13 +16,3 @@ public: private: ESP8266WebServer *obj_; }; - - -template -void saveSessionChunkToFile(const SessionChunk_T &chunk, const String &fileName) { - String startTimeStr(chunk.getStartTime()); - File f = SPIFFS.open(fileName, "w"); - StreamingMsgPackEncoder encoder(&f); - chunk.serialize(encoder); - f.close(); -} diff --git a/session/MockStorage.h b/session/MockStorage.h index dc8d38d..9320a36 100644 --- a/session/MockStorage.h +++ b/session/MockStorage.h @@ -3,18 +3,34 @@ #include #include +#include -class Adaptor { + +class VectorAdaptor { public: - Adaptor(const String &fileName) { + VectorAdaptor(std::vector * v) : v_(v) {} + + void write(const char *data, uint32_t size) { + v_->insert(v_->end(), data, data + size ); + } + +private: + std::vector * v_; +}; + +class FilePtrAdaptor { +public: + FilePtrAdaptor(const String &fileName) { static const String baseDirectory("."); auto fullFileName = baseDirectory + fileName; fptr = fopen(fullFileName.c_str(), "wb"); } - ~Adaptor() { + ~FilePtrAdaptor() { fclose(fptr); } + FilePtrAdaptor(const FilePtrAdaptor &) = delete; + void operator=(const FilePtrAdaptor &) = delete; void write(const char *data, uint32_t size) { fwrite(data, size, 1, fptr); @@ -28,8 +44,8 @@ private: class MockStorageWriter { public: MockStorageWriter(const String &fileName) { - adaptor_ = new Adaptor(fileName); - encoder_ = new StreamingMsgPackEncoder (adaptor_); + adaptor_ = new FilePtrAdaptor(fileName); + encoder_ = new StreamingMsgPackEncoder (adaptor_); } ~MockStorageWriter(){ delete adaptor_; @@ -37,11 +53,11 @@ public: } MockStorageWriter(const MockStorageWriter &) = delete; - StreamingMsgPackEncoder &encoder() { return *encoder_; } + StreamingMsgPackEncoder &encoder() { return *encoder_; } private: - Adaptor * adaptor_; - StreamingMsgPackEncoder * encoder_; + FilePtrAdaptor * adaptor_; + StreamingMsgPackEncoder * encoder_; }; diff --git a/session/Session.h b/session/Session.h index 8266f5b..58c4c9a 100644 --- a/session/Session.h +++ b/session/Session.h @@ -26,6 +26,16 @@ public: return true; } + void finalize() { + if( otherChunkFilled() ) + saveChunkToFile(otherChunk); + if( currentChunk->numMeasurements() > 0) { + saveChunkToFile(currentChunk); + } + currentChunk->init(0, 0); + otherChunk->init(0, 0); + } + template void serialize(StreamingMsgPackEncoder & encoder, uint32_t startIdx) const { diff --git a/session/SessionChunk.h b/session/SessionChunk.h index 7718fe1..3d3f780 100644 --- a/session/SessionChunk.h +++ b/session/SessionChunk.h @@ -42,9 +42,10 @@ public: void serialize(StreamingMsgPackEncoder & encoder) const { sendHeader(encoder, sessionStartTime, startIndex); - encoder.sendArray(values + startIndex, nextFree - startIndex); + encoder.sendArray(values, nextFree); } + /* template void serialize(StreamingMsgPackEncoder & encoder, uint32_t start, uint32_t end) const { @@ -67,7 +68,7 @@ public: const uint32_t length = min(nextFree, end - start); encoder.sendArray(values + idxStart, length); } - } + }*/ template static uint32_t valueOffset() diff --git a/sessiontest.cpp b/sessiontest.cpp index ca7a261..4e6c636 100644 --- a/sessiontest.cpp +++ b/sessiontest.cpp @@ -3,16 +3,149 @@ #include "session/Session.h" #include "session/MockStorage.h" +#include + const uint32_t SESSION_SIZE = 128; typedef Session MockSession; +template +std::vector parseMessagePack(const uint8_t * data, uint32_t &startTime, uint32_t &startIndex) +{ + int offset = 0; + + // map header + const int expectedMapSize = 3; + auto mapHeader = reinterpret_cast(&data[offset]); + offset += 1; + assert( *mapHeader == (0b10000000 | expectedMapSize), "Map Header wrong"); + + // string255: sessionStartTime + auto stringHeader = reinterpret_cast(&data[offset++]); + auto stringSize = reinterpret_cast(&data[offset++]); + assert(*stringHeader == '\xd9', "String header wrong"); + std::string sessionStartTimeStr = std::string((const char*)(&data[offset]), (size_t)(*stringSize)); + assert( sessionStartTimeStr == "sessionStartTime", "sessionStartTime string is wrong"); + offset += *stringSize; + + //uint32 + auto intCode = reinterpret_cast(&data[offset++]); + startTime = ntohl(*reinterpret_cast(&data[offset])); + offset += 4; + + // string255: startIndex + stringHeader = reinterpret_cast(&data[offset++]); + stringSize = reinterpret_cast(&data[offset++]); + assert(*stringHeader == '\xd9', "String header wrong"); + std::string startIndexStr = std::string((const char*)(&data[offset]), (size_t)(*stringSize)); + assert( startIndexStr == "startIndex", "startIndex string is wrong"); + offset += *stringSize; + + //uint32 + intCode = reinterpret_cast(&data[offset++]); + startIndex = ntohl(*reinterpret_cast(&data[offset])); + offset += 4; + + // string255: values + stringHeader = reinterpret_cast(&data[offset++]); + stringSize = reinterpret_cast(&data[offset++]); + assert(*stringHeader == '\xd9', "String header wrong"); + std::string valueStr = std::string((const char*)(&data[offset]), (size_t)(*stringSize)); + assert( valueStr == "values", "values string is wrong"); + offset += *stringSize; + + // vector + auto vectorHeader = reinterpret_cast(&data[offset++]); + assert( *vectorHeader == '\xc9', "Vector header wrong"); + size_t vectorLength = ntohl(*reinterpret_cast(&data[offset])) / sizeof(Measurement_T); + offset += 4; + offset += 1; // jump over type + + auto vectorData = reinterpret_cast(&data[offset]); + return std::vector(vectorData, vectorData + vectorLength); +} + + +void testSessionChunkAdd() +{ + const uint_t size = 16; + SessionChunk chunk; + for( uint16_t i=0; i < size; ++i) { + bool res = chunk.addPoint(i); + assert(res, "Adding point failed"); + assert( chunk.numMeasurements() == i+1, "Number of measurements reported wrong"); + } + bool res = chunk.addPoint(0); + assert(!res, "Full chunk was not detected"); + assert(chunk.numMeasurements() == size, "Point appears to be added"); +} + +void testSessionChunkGetterSetter() +{ + const uint_t size = 16; + SessionChunk chunk; + const uint32_t time = 244213; + const uint32_t startIdx = 131; + chunk.init(time, startIdx); + assert( chunk.getStartIndex() == startIdx, "Start Index wrong"); + assert( chunk.getStartTime() == time, "Start time wrong"); +} + +void testSessionChunkSerialization() +{ + const uint_t size = 16; + const uint32_t startTime = 194232; + const uint32_t startIndex = 1314; + const uint_t fillSize = 12; + + SessionChunk chunk; + chunk.init(startTime, startIndex); + for( uint16_t i=0; i < fillSize; ++i) { + bool res = chunk.addPoint(i); + assert(res, "Adding point failed"); + assert( chunk.numMeasurements() == i+1, "Number of measurements reported wrong"); + } + + std::vector data; + VectorAdaptor adaptor( &data ); + StreamingMsgPackEncoder encoder(&adaptor); + chunk.serialize(encoder); + uint32_t readStartTime=0; + uint32_t readStartIndex=0; + auto result = parseMessagePack(&data[0], readStartTime, readStartIndex); + assert(startIndex == readStartIndex && startTime == readStartTime, ""); + assert(result.size() == fillSize, "Wrong result array size"); + for( uint16_t i=0; i < fillSize; ++i) { + assert(result[i] == i, "Wrong array contents"); + } +} + + int main(int argc, char**argv) { - MockSession session; + testSessionChunkAdd(); + testSessionChunkGetterSetter(); + testSessionChunkSerialization(); - for( uint16_t i=0; i < SESSION_SIZE; ++i) { - session.addPoint(i); + //MockSession session; + + /* + std::string line; + while (std::getline(std::cin, line)) + { + std::stringstream lineStream(line); + std::string command; + lineStream >> command; + if( command == "add_points") { + uint16_t number; + lineStream >> number; + for( uint16_t i=0; i < number; ++i) { + session.addPoint(i); + } + } else if( command == "print_status") { + + } } + */ return 0; }