diff --git a/src/CBot/CBotFileUtils.cpp b/src/CBot/CBotFileUtils.cpp index c6d4169c..050205e3 100644 --- a/src/CBot/CBotFileUtils.cpp +++ b/src/CBot/CBotFileUtils.cpp @@ -342,7 +342,11 @@ bool WriteStream(std::ostream &ostr, std::istream& istr) if (!WriteLong(ostr, size)) return false; if (!istr.seekg(0, istr.beg)) return false; - if (!(ostr << istr.rdbuf())) return false; + while (size > 0) + { + size -= 1; + if (!ostr.put(istr.get())) return false; + } return true; } @@ -355,7 +359,7 @@ bool ReadStream(std::istream& istr, std::ostream &ostr) while (length-- > 0) { - if (!(ostr << istr.get())) return false; + if (!ostr.put(istr.get())) return false; } return true; } diff --git a/src/object/auto/autoegg.cpp b/src/object/auto/autoegg.cpp index 50354a8d..8abaec57 100644 --- a/src/object/auto/autoegg.cpp +++ b/src/object/auto/autoegg.cpp @@ -24,6 +24,7 @@ #include "graphics/engine/pyro_manager.h" +#include "level/parser/parser.h" #include "level/parser/parserline.h" #include "level/parser/parserparam.h" @@ -194,7 +195,9 @@ bool CAutoEgg::EventProcess(const Event &event) CProgramStorageObject* programStorage = dynamic_cast(alien); Program* program = programStorage->AddProgram(); - programStorage->ReadProgram(program, m_alienProgramName.c_str()); + programStorage->ReadProgram(program, InjectLevelPathsForCurrentLevel(m_alienProgramName, "ai")); + program->readOnly = true; + program->filename = m_alienProgramName; programmable->RunProgram(program); } Init(); diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 617f3245..cd715aeb 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -1226,7 +1226,7 @@ void COldObject::Read(CLevelParserLine* line) std::string op = "autoValue" + boost::lexical_cast(i+1); // autoValue1..autoValue5 m_auto->SetValue(i, line->GetParam(op)->AsFloat(0.0f)); } - m_auto->SetString(const_cast(line->GetParam("autoString")->AsPath("ai", "").c_str())); + m_auto->SetString(const_cast(line->GetParam("autoString")->AsString("").c_str())); int i = line->GetParam("run")->AsInt(-1); if (i != -1) diff --git a/test/unit/CBot/CBot_test.cpp b/test/unit/CBot/CBot_test.cpp index 87652aa0..3d1ee516 100644 --- a/test/unit/CBot/CBot_test.cpp +++ b/test/unit/CBot/CBot_test.cpp @@ -20,6 +20,7 @@ #include "CBot/CBot.h" #include +#include #include extern bool g_cbotTestSaveState; @@ -319,6 +320,200 @@ protected: } }; +TEST_F(CBotUT, TestSaveStateIOFunctions) +{ + std::stringstream sstr(""); + std::string teststring; + + for (char c = std::numeric_limits::min() ;; ++c) + { + teststring.push_back(c); + if ( c == std::numeric_limits::max() ) break; + } + + auto CallWriteFunctions = [&sstr, &teststring]() -> bool + { + if (!WriteWord(sstr, static_cast(0))) return false; + if (!WriteWord(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteWord(sstr, std::numeric_limits::max())) return false; + + if (!WriteByte(sstr, std::numeric_limits::min())) return false; + if (!WriteByte(sstr, std::numeric_limits::max())) return false; + + if (!WriteShort(sstr, std::numeric_limits::min())) return false; + if (!WriteShort(sstr, std::numeric_limits::min() / 2)) return false; + if (!WriteShort(sstr, -1)) return false; + if (!WriteShort(sstr, 0)) return false; + if (!WriteShort(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteShort(sstr, std::numeric_limits::max())) return false; + + if (!WriteUInt32(sstr, static_cast(0))) return false; + if (!WriteUInt32(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteUInt32(sstr, std::numeric_limits::max())) return false; + + if (!WriteInt(sstr, std::numeric_limits::min())) return false; + if (!WriteInt(sstr, std::numeric_limits::min() / 2)) return false; + if (!WriteInt(sstr, -1)) return false; + if (!WriteInt(sstr, 0)) return false; + if (!WriteInt(sstr, std::numeric_limits::max() / 2)) return false; + if (!WriteInt(sstr, std::numeric_limits::max())) return false; + + if (!WriteLong(sstr, std::numeric_limits::min())) return false; + if (!WriteLong(sstr, std::numeric_limits::min() / 2L)) return false; + if (!WriteLong(sstr, -1L)) return false; + if (!WriteLong(sstr, 0L)) return false; + if (!WriteLong(sstr, std::numeric_limits::max() / 2L)) return false; + if (!WriteLong(sstr, std::numeric_limits::max())) return false; + + // test with padding bytes (not currently used anywhere) + if (!WriteLong(sstr, 1234567890L, 10)) return false; + + if (!WriteFloat(sstr, std::numeric_limits::min())) return false; + if (!WriteFloat(sstr, 0.0f)) return false; + if (!WriteFloat(sstr, std::numeric_limits::max())) return false; + + if (!WriteDouble(sstr, std::numeric_limits::min())) return false; + if (!WriteDouble(sstr, 0.0)) return false; + if (!WriteDouble(sstr, std::numeric_limits::max())) return false; + + if (!WriteString(sstr, "")) return false; + if (!WriteString(sstr, teststring)) return false; + return true; + }; + + if ( !CallWriteFunctions() ) + { + ADD_FAILURE() << "failed in CallWriteFunctions()" << std::endl; + return; + } + + std::stringstream savestream(""); + + if ( !WriteStream(savestream, sstr) ) + { + ADD_FAILURE() << "CBot::WriteStream() failed" << std::endl; + return; + } + + std::stringstream newstream(""); + + if ( !ReadStream(savestream, newstream) ) + { + ADD_FAILURE() << "CBot:ReadStream() failed" << std::endl; + return; + } + + auto CallReadFunctions = [&teststring, &newstream]() -> bool + { + unsigned short w = 1; + if (!ReadWord(newstream, w)) return false; + if (w != static_cast(0)) return false; + if (!ReadWord(newstream, w)) return false; + if (w != std::numeric_limits::max() / 2) return false; + + if (!ReadWord(newstream, w)) return false; + if (w != std::numeric_limits::max()) return false; + + char c = 1; + if (!ReadByte(newstream, c)) return false; + if (c != std::numeric_limits::min()) return false; + if (!ReadByte(newstream, c)) return false; + if (c != std::numeric_limits::max()) return false; + + short s = 1; + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::min()) return false; + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::min() / 2) return false; + + if (!ReadShort(newstream, s)) return false; + if (s != -1) return false; + if (!ReadShort(newstream, s)) return false; + if (s != 0) return false; + + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::max() / 2) return false; + if (!ReadShort(newstream, s)) return false; + if (s != std::numeric_limits::max()) return false; + + uint32_t u = 1; + if (!ReadUInt32(newstream, u)) return false; + if (u != static_cast(0)) return false; + if (!ReadUInt32(newstream, u)) return false; + if (u != std::numeric_limits::max() / 2) return false; + + if (!ReadUInt32(newstream, u)) return false; + if (u != std::numeric_limits::max()) return false; + + int i = 1; + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::min()) return false; + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::min() / 2) return false; + + if (!ReadInt(newstream, i)) return false; + if (i != -1) return false; + if (!ReadInt(newstream, i)) return false; + if (i != 0) return false; + + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::max() / 2) return false; + if (!ReadInt(newstream, i)) return false; + if (i != std::numeric_limits::max()) return false; + + long l = 1L; + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::min()) return false; + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::min() / 2L) return false; + + if (!ReadLong(newstream, l)) return false; + if (l != -1L) return false; + if (!ReadLong(newstream, l)) return false; + if (l != 0L) return false; + + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::max() / 2L) return false; + if (!ReadLong(newstream, l)) return false; + if (l != std::numeric_limits::max()) return false; + + if (!ReadLong(newstream, l)) return false; + if (l != 1234567890L) return false; + + float f = 1.0f; + if (!ReadFloat(newstream, f)) return false; + if (f != std::numeric_limits::min()) return false; + if (!ReadFloat(newstream, f)) return false; + if (f != 0.0f) return false; + + if (!ReadFloat(newstream, f)) return false; + if (f != std::numeric_limits::max()) return false; + + double d = 1.0; + if (!ReadDouble(newstream, d)) return false; + if (d != std::numeric_limits::min()) return false; + if (!ReadDouble(newstream, d)) return false; + if (d != 0.0) return false; + + if (!ReadDouble(newstream, d)) return false; + if (d != std::numeric_limits::max()) return false; + + std::string newstring = "should be empty string after next read"; + if (!ReadString(newstream, newstring)) return false; + if (newstring != "") return false; + + if (!ReadString(newstream, newstring)) return false; + if (newstring != teststring) return false; + return true; + }; + + if ( !CallReadFunctions() ) + { + ADD_FAILURE() << "failed in CallReadFunctions()" << std::endl; + return; + } +} + TEST_F(CBotUT, EmptyTest) { ExecuteTest(