1#include <base/hash.h>
2#include <base/logger.h>
3#include <base/os.h>
4#include <base/str.h>
5
6#include <engine/map.h>
7#include <engine/shared/uuid_manager.h>
8#include <engine/storage.h>
9
10static const char *TOOL_NAME = "map_test";
11
12static int TestMap(const char *pMapPath, bool CalcHashes, IStorage *pStorage)
13{
14 log_info(TOOL_NAME, "Testing map '%s'...", pMapPath);
15
16 std::unique_ptr<IMap> pMap = CreateMap();
17 if(!pMap->Load(pStorage, pPath: pMapPath, StorageType: IStorage::TYPE_ABSOLUTE))
18 {
19 log_error(TOOL_NAME, "Failed to open map '%s' for reading", pMapPath);
20 return -1;
21 }
22
23 char aSha256Str[SHA256_MAXSTRSIZE];
24 sha256_str(digest: pMap->Sha256(), str: aSha256Str, max_len: sizeof(aSha256Str));
25 log_info(TOOL_NAME, "File size: %d", pMap->Size());
26 log_info(TOOL_NAME, "File SHA256: %s", aSha256Str);
27 log_info(TOOL_NAME, "File CRC32: %08x", pMap->Crc());
28 log_info(TOOL_NAME, "Num items: %d", pMap->NumItems());
29 log_info(TOOL_NAME, "Num data: %d", pMap->NumData());
30
31 for(int Index = 0; Index < pMap->NumItems(); Index++)
32 {
33 log_info(TOOL_NAME, "Item %d:", Index);
34
35 int Type, Id;
36 CUuid Uuid;
37 const void *pItem = pMap->GetItem(Index, pType: &Type, pId: &Id, pUuid: &Uuid);
38
39 log_info(TOOL_NAME, " Type: %d", Type);
40 log_info(TOOL_NAME, " ID: %d", Id);
41 char aUuidStr[UUID_MAXSTRSIZE];
42 FormatUuid(Uuid, pBuffer: aUuidStr, BufferLength: sizeof(aUuidStr));
43 log_info(TOOL_NAME, " UUID: %s", aUuidStr);
44
45 const int Size = pMap->GetItemSize(Index);
46 log_info(TOOL_NAME, " Size: %d bytes", Size);
47
48 if(CalcHashes)
49 {
50 const SHA256_DIGEST ItemDataSha256 = sha256(message: pItem, message_len: Size);
51 sha256_str(digest: ItemDataSha256, str: aSha256Str, max_len: sizeof(aSha256Str));
52 log_info(TOOL_NAME, " Data (SHA256): %s", aSha256Str);
53 }
54 }
55
56 for(int Index = 0; Index < pMap->NumData(); Index++)
57 {
58 log_info(TOOL_NAME, "Data %d:", Index);
59
60 // The data must be loaded first, as the size is only final after the data has been processed.
61 const void *pData = pMap->GetData(Index);
62 const int Size = pMap->GetDataSize(Index);
63 log_info(TOOL_NAME, " Size: %d bytes", Size);
64
65 if(pData == nullptr)
66 {
67 log_info(TOOL_NAME, " Data erroneous");
68 }
69 else if(CalcHashes)
70 {
71 const SHA256_DIGEST ItemDataSha256 = sha256(message: pData, message_len: Size);
72 sha256_str(digest: ItemDataSha256, str: aSha256Str, max_len: sizeof(aSha256Str));
73 log_info(TOOL_NAME, " Data (SHA256): %s", aSha256Str);
74 }
75
76 pMap->UnloadData(Index);
77 }
78
79 pMap->Unload();
80 log_info(TOOL_NAME, "Tested map '%s' successfully", pMapPath);
81 return 0;
82}
83
84int main(int argc, const char **argv)
85{
86 const CCmdlineFix CmdlineFix(&argc, &argv);
87 ILogger *pDefaultLogger = log_logger_default().release();
88 pDefaultLogger->SetFilter(CLogFilter{.m_MaxLevel: LEVEL_DEBUG});
89 log_set_global_logger(logger: pDefaultLogger);
90
91 const char *pMapPath;
92 bool CalcHashes;
93 if(argc == 2)
94 {
95 pMapPath = argv[1];
96 CalcHashes = false;
97 }
98 else if(argc == 3 && str_comp(a: argv[1], b: "--calc-hashes") == 0)
99 {
100 pMapPath = argv[2];
101 CalcHashes = true;
102 }
103 else
104 {
105 log_error(TOOL_NAME, "Usage: %s [--calc-hashes] <map>", TOOL_NAME);
106 return -1;
107 }
108
109 std::unique_ptr<IStorage> pStorage = std::unique_ptr<IStorage>(CreateStorage(InitializationType: IStorage::EInitializationType::BASIC, NumArgs: argc, ppArguments: argv));
110 if(!pStorage)
111 {
112 log_error(TOOL_NAME, "Error creating basic storage");
113 return -1;
114 }
115
116 return TestMap(pMapPath, CalcHashes, pStorage: pStorage.get());
117}
118