1
0

test-gguf.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344
  1. #include "ggml.h"
  2. #include "ggml-backend.h"
  3. #include "../ggml/src/ggml-impl.h"
  4. #include <algorithm>
  5. #include <array>
  6. #include <cstdint>
  7. #include <cstdio>
  8. #include <random>
  9. #include <string>
  10. #include <vector>
  11. constexpr int offset_has_kv = 1000;
  12. constexpr int offset_has_tensors = 2000;
  13. constexpr int offset_has_data = 3000;
  14. enum handcrafted_file_type {
  15. HANDCRAFTED_HEADER_BAD_MAGIC = 10,
  16. HANDCRAFTED_HEADER_BAD_VERSION_0 = 15,
  17. HANDCRAFTED_HEADER_BAD_VERSION_1 = 20,
  18. HANDCRAFTED_HEADER_BAD_VERSION_FUTURE = 30,
  19. HANDCRAFTED_HEADER_BAD_N_TENSORS = 40,
  20. HANDCRAFTED_HEADER_BAD_N_KV = 50,
  21. HANDCRAFTED_HEADER_EMPTY = 800,
  22. HANDCRAFTED_KV_BAD_KEY_SIZE = 10 + offset_has_kv,
  23. HANDCRAFTED_KV_BAD_TYPE = 20 + offset_has_kv,
  24. // HANDCRAFTED_KV_BAD_VALUE_SIZE = 30 + offset_has_kv, // removed because it can result in allocations > 1 TB (default sanitizer limit)
  25. HANDCRAFTED_KV_DUPLICATE_KEY = 40 + offset_has_kv,
  26. HANDCRAFTED_KV_BAD_ALIGN = 50 + offset_has_kv,
  27. HANDCRAFTED_KV_SUCCESS = 800 + offset_has_kv,
  28. HANDCRAFTED_TENSORS_BAD_NAME_SIZE = 10 + offset_has_tensors,
  29. HANDCRAFTED_TENSORS_BAD_N_DIMS = 20 + offset_has_tensors,
  30. HANDCRAFTED_TENSORS_BAD_SHAPE = 30 + offset_has_tensors,
  31. HANDCRAFTED_TENSORS_NE_TOO_BIG = 40 + offset_has_tensors,
  32. HANDCRAFTED_TENSORS_BAD_TYPE = 50 + offset_has_tensors,
  33. HANDCRAFTED_TENSORS_BAD_OFFSET = 60 + offset_has_tensors,
  34. HANDCRAFTED_TENSORS_DUPLICATE_NAME = 70 + offset_has_tensors,
  35. HANDCRAFTED_TENSORS_BAD_ALIGN = 75 + offset_has_tensors,
  36. HANDCRAFTED_TENSORS_INCONSISTENT_ALIGN = 80 + offset_has_tensors,
  37. HANDCRAFTED_TENSORS_SUCCESS = 800 + offset_has_tensors,
  38. HANDCRAFTED_TENSORS_CUSTOM_ALIGN = 810 + offset_has_tensors,
  39. HANDCRAFTED_DATA_NOT_ENOUGH_DATA = 10 + offset_has_data,
  40. HANDCRAFTED_DATA_BAD_ALIGN = 15 + offset_has_data,
  41. HANDCRAFTED_DATA_INCONSISTENT_ALIGN = 20 + offset_has_data,
  42. HANDCRAFTED_DATA_SUCCESS = 800 + offset_has_data,
  43. HANDCRAFTED_DATA_CUSTOM_ALIGN = 810 + offset_has_data,
  44. };
  45. static std::string handcrafted_file_type_name(const enum handcrafted_file_type hft) {
  46. switch (hft) {
  47. case HANDCRAFTED_HEADER_BAD_MAGIC: return "HEADER_BAD_MAGIC";
  48. case HANDCRAFTED_HEADER_BAD_VERSION_0: return "HEADER_BAD_VERSION_0";
  49. case HANDCRAFTED_HEADER_BAD_VERSION_1: return "HEADER_BAD_VERSION_1";
  50. case HANDCRAFTED_HEADER_BAD_VERSION_FUTURE: return "HEADER_BAD_VERSION_FUTURE";
  51. case HANDCRAFTED_HEADER_BAD_N_KV: return "HEADER_BAD_N_KV";
  52. case HANDCRAFTED_HEADER_BAD_N_TENSORS: return "HEADER_BAD_N_TENSORS";
  53. case HANDCRAFTED_HEADER_EMPTY: return "HEADER_EMPTY";
  54. case HANDCRAFTED_KV_BAD_KEY_SIZE: return "KV_BAD_KEY_SIZE";
  55. case HANDCRAFTED_KV_BAD_TYPE: return "KV_BAD_TYPE";
  56. case HANDCRAFTED_KV_DUPLICATE_KEY: return "KV_DUPLICATE_KEY";
  57. case HANDCRAFTED_KV_BAD_ALIGN: return "KV_BAD_ALIGN";
  58. case HANDCRAFTED_KV_SUCCESS: return "KV_RANDOM_KV";
  59. case HANDCRAFTED_TENSORS_BAD_NAME_SIZE: return "TENSORS_BAD_NAME_SIZE";
  60. case HANDCRAFTED_TENSORS_BAD_N_DIMS: return "TENSORS_BAD_N_DIMS";
  61. case HANDCRAFTED_TENSORS_BAD_SHAPE: return "TENSORS_BAD_SHAPE";
  62. case HANDCRAFTED_TENSORS_NE_TOO_BIG: return "TENSORS_NE_TOO_BIG";
  63. case HANDCRAFTED_TENSORS_BAD_TYPE: return "TENSORS_BAD_TYPE";
  64. case HANDCRAFTED_TENSORS_BAD_OFFSET: return "TENSORS_BAD_OFFSET";
  65. case HANDCRAFTED_TENSORS_DUPLICATE_NAME: return "TENSORS_DUPLICATE_NAME";
  66. case HANDCRAFTED_TENSORS_BAD_ALIGN: return "TENSORS_BAD_ALIGN";
  67. case HANDCRAFTED_TENSORS_INCONSISTENT_ALIGN: return "TENSORS_INCONSISTENT_ALIGN";
  68. case HANDCRAFTED_TENSORS_SUCCESS: return "TENSORS_SUCCESS";
  69. case HANDCRAFTED_TENSORS_CUSTOM_ALIGN: return "TENSORS_CUSTOM_ALIGN";
  70. case HANDCRAFTED_DATA_NOT_ENOUGH_DATA: return "DATA_NOT_ENOUGH_DATA";
  71. case HANDCRAFTED_DATA_BAD_ALIGN: return "DATA_BAD_ALIGN";
  72. case HANDCRAFTED_DATA_INCONSISTENT_ALIGN: return "DATA_INCONSISTENT_ALIGN";
  73. case HANDCRAFTED_DATA_SUCCESS: return "DATA_SUCCESS";
  74. case HANDCRAFTED_DATA_CUSTOM_ALIGN: return "DATA_CUSTOM_ALIGN";
  75. }
  76. GGML_ABORT("fatal error");
  77. }
  78. static bool expect_context_not_null(const enum handcrafted_file_type hft) {
  79. if (hft < offset_has_kv) {
  80. return hft >= HANDCRAFTED_HEADER_EMPTY;
  81. }
  82. if (hft < offset_has_tensors) {
  83. return hft >= HANDCRAFTED_KV_SUCCESS;
  84. }
  85. if (hft < offset_has_data) {
  86. return hft >= HANDCRAFTED_TENSORS_SUCCESS;
  87. }
  88. return hft >= HANDCRAFTED_DATA_SUCCESS;
  89. }
  90. typedef std::pair<enum ggml_type, std::array<int64_t, GGML_MAX_DIMS>> tensor_config_t;
  91. static std::vector<tensor_config_t> get_tensor_configs(std::mt19937 & rng) {
  92. std::vector<tensor_config_t> tensor_configs;
  93. tensor_configs.reserve(100);
  94. for (int i = 0; i < 100; ++i) {
  95. const enum ggml_type type = ggml_type(rng() % GGML_TYPE_COUNT);
  96. if (ggml_type_size(type) == 0) {
  97. continue;
  98. }
  99. std::array<int64_t, GGML_MAX_DIMS> shape = {1, 1, 1, 1};
  100. shape[0] = (1 + rng() % 10) * ggml_blck_size(type);
  101. const int n_dims = 1 + rng() % GGML_MAX_DIMS;
  102. for (int i = 1; i < n_dims; ++i) {
  103. shape[i] = 1 + rng() % 10;
  104. }
  105. tensor_configs.push_back(std::make_pair(type, shape));
  106. }
  107. return tensor_configs;
  108. }
  109. static std::vector<std::pair<enum gguf_type, enum gguf_type>> get_kv_types(std::mt19937 rng) {
  110. std::vector<std::pair<enum gguf_type, enum gguf_type>> kv_types;
  111. kv_types.reserve(100);
  112. for (int i = 0; i < 100; ++i) {
  113. const gguf_type type = gguf_type(rng() % GGUF_TYPE_COUNT);
  114. if (type == GGUF_TYPE_ARRAY) {
  115. const gguf_type type_arr = gguf_type(rng() % GGUF_TYPE_COUNT);
  116. if (type_arr == GGUF_TYPE_ARRAY) {
  117. continue;
  118. }
  119. kv_types.push_back(std::make_pair(type, type_arr));
  120. continue;
  121. }
  122. kv_types.push_back(std::make_pair(type, gguf_type(-1)));
  123. }
  124. std::shuffle(kv_types.begin(), kv_types.end(), rng);
  125. return kv_types;
  126. }
  127. template <typename T>
  128. static void helper_write(FILE * file, const T & val) {
  129. GGML_ASSERT(fwrite(&val, 1, sizeof(val), file) == sizeof(val));
  130. }
  131. static void helper_write(FILE * file, const void * data, const size_t nbytes) {
  132. GGML_ASSERT(fwrite(data, 1, nbytes, file) == nbytes);
  133. }
  134. static FILE * get_handcrafted_file(const unsigned int seed, const enum handcrafted_file_type hft, const int extra_bytes = 0) {
  135. FILE * file = tmpfile();
  136. if (!file) {
  137. return file;
  138. }
  139. std::mt19937 rng(seed);
  140. uint32_t alignment = GGUF_DEFAULT_ALIGNMENT;
  141. if (hft == HANDCRAFTED_HEADER_BAD_MAGIC) {
  142. const char bad_magic[4] = {'F', 'U', 'G', 'G'};
  143. helper_write(file, bad_magic, sizeof(bad_magic));
  144. } else {
  145. helper_write(file, GGUF_MAGIC, 4);
  146. }
  147. if (hft == HANDCRAFTED_HEADER_BAD_VERSION_0) {
  148. const uint32_t version = 0;
  149. helper_write(file, version);
  150. } else if (hft == HANDCRAFTED_HEADER_BAD_VERSION_1) {
  151. const uint32_t version = 1;
  152. helper_write(file, version);
  153. } else if (hft == HANDCRAFTED_HEADER_BAD_VERSION_FUTURE) {
  154. const uint32_t version = GGUF_VERSION + 1;
  155. helper_write(file, version);
  156. } else {
  157. const uint32_t version = GGUF_VERSION;
  158. helper_write(file, version);
  159. }
  160. std::vector<tensor_config_t> tensor_configs;
  161. if (hft >= offset_has_tensors) {
  162. tensor_configs = get_tensor_configs(rng);
  163. }
  164. if (hft == HANDCRAFTED_HEADER_BAD_N_TENSORS) {
  165. const uint64_t n_tensors = -1;
  166. helper_write(file, n_tensors);
  167. } else {
  168. const uint64_t n_tensors = tensor_configs.size();
  169. helper_write(file, n_tensors);
  170. }
  171. std::vector<std::pair<enum gguf_type, enum gguf_type>> kv_types;
  172. if (hft >= offset_has_kv) {
  173. kv_types = get_kv_types(rng);
  174. }
  175. {
  176. uint64_t n_kv = kv_types.size();
  177. if (hft == HANDCRAFTED_KV_BAD_ALIGN ||
  178. hft == HANDCRAFTED_TENSORS_BAD_ALIGN || hft == HANDCRAFTED_TENSORS_CUSTOM_ALIGN ||
  179. hft == HANDCRAFTED_DATA_BAD_ALIGN || hft == HANDCRAFTED_DATA_CUSTOM_ALIGN) {
  180. n_kv += 1;
  181. } else if (hft == HANDCRAFTED_HEADER_BAD_N_KV) {
  182. n_kv = -1;
  183. }
  184. helper_write(file, n_kv);
  185. }
  186. if (hft < offset_has_kv) {
  187. while (ftell(file) % alignment != 0) {
  188. const char pad = 0;
  189. helper_write(file, pad);
  190. }
  191. for (int i = 0; i < extra_bytes; ++i) {
  192. const char tmp = 0;
  193. helper_write(file, tmp);
  194. }
  195. rewind(file);
  196. return file;
  197. }
  198. for (int i = 0; i < int(kv_types.size()); ++i) {
  199. const enum gguf_type type = gguf_type(hft == HANDCRAFTED_KV_BAD_TYPE ? GGUF_TYPE_COUNT : kv_types[i].first);
  200. const enum gguf_type type_arr = gguf_type(hft == HANDCRAFTED_KV_BAD_TYPE ? GGUF_TYPE_COUNT : kv_types[i].second);
  201. const std::string key = "my_key_" + std::to_string((hft == HANDCRAFTED_KV_DUPLICATE_KEY ? i/2 : i));
  202. if (hft == HANDCRAFTED_KV_BAD_KEY_SIZE) {
  203. const uint64_t n = -1;
  204. helper_write(file, n);
  205. } else {
  206. const uint64_t n = key.length();
  207. helper_write(file, n);
  208. }
  209. helper_write(file, key.data(), key.length());
  210. {
  211. const int32_t type32 = int32_t(type);
  212. helper_write(file, type32);
  213. }
  214. uint32_t data[16];
  215. for (int j = 0; j < 16; ++j) {
  216. data[j] = rng();
  217. if (type == GGUF_TYPE_STRING || type_arr == GGUF_TYPE_STRING) {
  218. data[j] |= 0x01010101; // avoid random null-termination of string
  219. }
  220. }
  221. if (type == GGUF_TYPE_STRING) {
  222. const uint64_t n = rng() % sizeof(data);
  223. helper_write(file, n);
  224. helper_write(file, data, n);
  225. continue;
  226. }
  227. if (type == GGUF_TYPE_ARRAY) {
  228. {
  229. const int32_t type32 = int32_t(type_arr);
  230. helper_write(file, type32);
  231. }
  232. if (type_arr == GGUF_TYPE_STRING) {
  233. const uint64_t nstr = rng() % (16 + 1);
  234. helper_write(file, nstr);
  235. for (uint64_t istr = 0; istr < nstr; ++istr) {
  236. const uint64_t n = rng() % (sizeof(uint32_t) + 1);
  237. helper_write(file, n);
  238. helper_write(file, &data[istr], n);
  239. }
  240. continue;
  241. }
  242. const size_t type_size = gguf_type_size(type_arr);
  243. const uint64_t n = (rng() % sizeof(data)) / type_size;
  244. helper_write(file, n);
  245. helper_write(file, &data, n*type_size);
  246. continue;
  247. }
  248. helper_write(file, data, hft == HANDCRAFTED_KV_BAD_TYPE ? 1 : gguf_type_size(type));
  249. }
  250. if (hft == HANDCRAFTED_KV_BAD_ALIGN ||
  251. hft == HANDCRAFTED_TENSORS_BAD_ALIGN || hft == HANDCRAFTED_TENSORS_CUSTOM_ALIGN ||
  252. hft == HANDCRAFTED_DATA_BAD_ALIGN || hft == HANDCRAFTED_DATA_CUSTOM_ALIGN) {
  253. const uint64_t n = strlen(GGUF_KEY_GENERAL_ALIGNMENT);
  254. helper_write(file, n);
  255. helper_write(file, GGUF_KEY_GENERAL_ALIGNMENT, n);
  256. const int32_t type = gguf_type(GGUF_TYPE_UINT32);
  257. helper_write(file, type);
  258. alignment = expect_context_not_null(hft) ? 1 : 13;
  259. helper_write(file, alignment);
  260. }
  261. if (hft < offset_has_tensors) {
  262. while (ftell(file) % alignment != 0) {
  263. const char pad = 0;
  264. helper_write(file, pad);
  265. }
  266. for (int i = 0; i < extra_bytes; ++i) {
  267. const char tmp = 0;
  268. helper_write(file, tmp);
  269. }
  270. rewind(file);
  271. return file;
  272. }
  273. if (hft == HANDCRAFTED_TENSORS_INCONSISTENT_ALIGN || hft == HANDCRAFTED_DATA_INCONSISTENT_ALIGN) {
  274. alignment = 1;
  275. }
  276. uint64_t offset = 0;
  277. for (int i = 0; i < int(tensor_configs.size()); ++i) {
  278. const ggml_type type = tensor_configs[i].first;
  279. const std::array<int64_t, GGML_MAX_DIMS> shape = tensor_configs[i].second;
  280. std::string name = "my_tensor";
  281. if (hft != HANDCRAFTED_TENSORS_DUPLICATE_NAME) {
  282. name += "_" + std::to_string(i);
  283. }
  284. if (hft == HANDCRAFTED_TENSORS_BAD_NAME_SIZE) {
  285. name += "_with_a_very_long_name_which_is_longer_than_what_is_allowed_for_ggml_tensors";
  286. GGML_ASSERT(name.length() >= GGML_MAX_NAME);
  287. }
  288. {
  289. const uint64_t n = name.length();
  290. helper_write(file, n);
  291. }
  292. helper_write(file, name.data(), name.length());
  293. uint32_t n_dims = hft == HANDCRAFTED_TENSORS_NE_TOO_BIG ? 2 : 1;
  294. for (int i = GGML_MAX_DIMS-1; i >= 1; --i) {
  295. if (shape[i] != 1) {
  296. n_dims = i + 1;
  297. break;
  298. }
  299. }
  300. if (hft == HANDCRAFTED_TENSORS_BAD_N_DIMS) {
  301. const uint32_t n_dims_bad = GGML_MAX_DIMS + 1;
  302. helper_write(file, n_dims_bad);
  303. } else {
  304. helper_write(file, n_dims);
  305. }
  306. if (hft == HANDCRAFTED_TENSORS_BAD_SHAPE) {
  307. for (uint32_t j = 0; j < n_dims; ++j) {
  308. const int64_t bad_dim = -1;
  309. helper_write(file, bad_dim);
  310. }
  311. } else if (hft == HANDCRAFTED_TENSORS_NE_TOO_BIG){
  312. for (uint32_t j = 0; j < n_dims; ++j) {
  313. const int64_t big_dim = 4*int64_t(INT32_MAX);
  314. helper_write(file, big_dim);
  315. }
  316. } else {
  317. helper_write(file, shape.data(), n_dims*sizeof(int64_t));
  318. }
  319. {
  320. const int32_t type32 = hft == HANDCRAFTED_TENSORS_BAD_TYPE ? GGML_TYPE_COUNT : int32_t(type);
  321. helper_write(file, type32);
  322. }
  323. if (hft == HANDCRAFTED_TENSORS_BAD_OFFSET) {
  324. const uint64_t bad_offset = -1;
  325. helper_write(file, bad_offset);
  326. } else {
  327. helper_write(file, offset);
  328. }
  329. int64_t ne = shape[0];
  330. for (uint32_t i = 1; i < n_dims; ++i) {
  331. ne *= shape[i];
  332. }
  333. offset += GGML_PAD(ggml_row_size(type, ne), alignment);
  334. }
  335. while (ftell(file) % alignment != 0) {
  336. const char pad = 0;
  337. helper_write(file, pad);
  338. }
  339. if (hft >= offset_has_data) {
  340. rng.seed(seed + 1);
  341. uint64_t nbytes = offset;
  342. if (hft == HANDCRAFTED_DATA_NOT_ENOUGH_DATA) {
  343. nbytes -= 1;
  344. }
  345. for (uint64_t i = 0; i < nbytes; ++i) {
  346. const uint8_t random_byte = i % 256;
  347. helper_write(file, random_byte);
  348. }
  349. }
  350. for (int i = 0; i < extra_bytes; ++i) {
  351. const char tmp = 0;
  352. helper_write(file, tmp);
  353. }
  354. rewind(file);
  355. return file;
  356. }
  357. static bool handcrafted_check_header(const gguf_context * gguf_ctx, const unsigned int seed, const bool has_kv, const bool has_tensors, const bool alignment_defined) {
  358. if (!gguf_ctx) {
  359. return false;
  360. }
  361. std::mt19937 rng(seed);
  362. std::vector<tensor_config_t> tensor_configs;
  363. if (has_tensors) {
  364. tensor_configs = get_tensor_configs(rng);
  365. }
  366. std::vector<std::pair<enum gguf_type, enum gguf_type>> kv_types;
  367. if (has_kv) {
  368. kv_types = get_kv_types(rng);
  369. }
  370. bool ok = true;
  371. if (gguf_get_version(gguf_ctx) != GGUF_VERSION) {
  372. ok = false;
  373. }
  374. if (gguf_get_n_tensors(gguf_ctx) != int(tensor_configs.size())) {
  375. ok = false;
  376. }
  377. if (gguf_get_n_kv(gguf_ctx) != int(alignment_defined ? kv_types.size() + 1 : kv_types.size())) {
  378. ok = false;
  379. }
  380. return ok;
  381. }
  382. static bool handcrafted_check_kv(const gguf_context * gguf_ctx, const unsigned int seed, const bool has_tensors, const bool alignment_defined) {
  383. if (!gguf_ctx) {
  384. return false;
  385. }
  386. std::mt19937 rng(seed);
  387. std::vector<tensor_config_t> tensor_configs;
  388. if (has_tensors) {
  389. tensor_configs = get_tensor_configs(rng);
  390. }
  391. std::vector<std::pair<enum gguf_type, enum gguf_type>> kv_types = get_kv_types(rng);
  392. bool ok = true;
  393. for (int i = 0; i < int(kv_types.size()); ++i) {
  394. const enum gguf_type type = gguf_type(kv_types[i].first);
  395. const enum gguf_type type_arr = gguf_type(kv_types[i].second);
  396. const std::string key = "my_key_" + std::to_string(i);
  397. uint32_t data[16];
  398. for (int j = 0; j < 16; ++j) {
  399. data[j] = rng();
  400. if (type == GGUF_TYPE_STRING || type_arr == GGUF_TYPE_STRING) {
  401. data[j] |= 0x01010101; // avoid random null-termination of string
  402. }
  403. }
  404. const char * data8 = reinterpret_cast<const char *>(data);
  405. const int id = gguf_find_key(gguf_ctx, key.c_str());
  406. if (type == GGUF_TYPE_STRING) {
  407. const char * str = gguf_get_val_str(gguf_ctx, id);
  408. const uint64_t n = strlen(str);
  409. const uint64_t n_expected = rng() % sizeof(data);
  410. if (n != n_expected) {
  411. ok = false;
  412. continue;
  413. }
  414. if (!std::equal(str, str + n, data8)) {
  415. ok = false;
  416. }
  417. continue;
  418. }
  419. if (type == GGUF_TYPE_ARRAY) {
  420. const size_t type_size = gguf_type_size(type_arr);
  421. const uint64_t arr_n = gguf_get_arr_n(gguf_ctx, id);
  422. if (type_arr == GGUF_TYPE_STRING) {
  423. const uint64_t nstr_expected = rng() % (16 + 1);
  424. if (arr_n != nstr_expected) {
  425. ok = false;
  426. continue;
  427. }
  428. for (uint64_t istr = 0; istr < nstr_expected; ++istr) {
  429. const char * str = gguf_get_arr_str(gguf_ctx, id, istr);
  430. const uint64_t n = strlen(str);
  431. const uint64_t n_expected = rng() % (sizeof(uint32_t) + 1);
  432. if (n != n_expected) {
  433. ok = false;
  434. continue;
  435. }
  436. const char * str_expected = reinterpret_cast<const char *>(&data[istr]);
  437. if (strncmp(str, str_expected, n) != 0) {
  438. ok = false;
  439. continue;
  440. }
  441. }
  442. continue;
  443. }
  444. const uint64_t arr_n_expected = (rng() % sizeof(data)) / type_size;
  445. if (arr_n != arr_n_expected) {
  446. ok = false;
  447. continue;
  448. }
  449. const char * data_gguf = reinterpret_cast<const char *>(gguf_get_arr_data(gguf_ctx, id));
  450. if (type_arr == GGUF_TYPE_BOOL) {
  451. for (size_t arr_i = 0; arr_i < arr_n; ++arr_i) {
  452. if (bool(data8[arr_i]) != bool(data_gguf[arr_i])) {
  453. ok = false;
  454. }
  455. }
  456. continue;
  457. }
  458. if (!std::equal(data8, data8 + arr_n*type_size, data_gguf)) {
  459. ok = false;
  460. }
  461. continue;
  462. }
  463. const char * data_gguf = reinterpret_cast<const char *>(gguf_get_val_data(gguf_ctx, id));
  464. if (type == GGUF_TYPE_BOOL) {
  465. if (bool(*data8) != bool(*data_gguf)) {
  466. ok = false;
  467. }
  468. continue;
  469. }
  470. if (!std::equal(data8, data8 + gguf_type_size(type), data_gguf)) {
  471. ok = false;
  472. }
  473. }
  474. const uint32_t expected_alignment = alignment_defined ? 1 : GGUF_DEFAULT_ALIGNMENT;
  475. if (gguf_get_alignment(gguf_ctx) != expected_alignment) {
  476. ok = false;
  477. }
  478. return ok;
  479. }
  480. static bool handcrafted_check_tensors(const gguf_context * gguf_ctx, const unsigned int seed) {
  481. if (!gguf_ctx) {
  482. return false;
  483. }
  484. std::mt19937 rng(seed);
  485. std::vector<tensor_config_t> tensor_configs = get_tensor_configs(rng);
  486. // Call get_kv_types to get the same RNG state:
  487. get_kv_types(rng);
  488. bool ok = true;
  489. const int id_alignment = gguf_find_key(gguf_ctx, GGUF_KEY_GENERAL_ALIGNMENT);
  490. const uint32_t alignment = id_alignment >= 0 ? gguf_get_val_u32(gguf_ctx, id_alignment) : GGUF_DEFAULT_ALIGNMENT;
  491. uint64_t expected_offset = 0;
  492. for (int i = 0; i < int(tensor_configs.size()); ++i) {
  493. const ggml_type type = tensor_configs[i].first;
  494. const std::array<int64_t, GGML_MAX_DIMS> shape = tensor_configs[i].second;
  495. const std::string name = "my_tensor_" + std::to_string(i);
  496. const int id = gguf_find_tensor(gguf_ctx, name.c_str());
  497. if (id >= 0) {
  498. if (std::string(gguf_get_tensor_name(gguf_ctx, id)) != name) {
  499. ok = false;
  500. }
  501. if (gguf_get_tensor_type(gguf_ctx, id) != type) {
  502. ok = false;
  503. }
  504. } else {
  505. ok = false;
  506. continue;
  507. }
  508. const size_t offset = gguf_get_tensor_offset(gguf_ctx, id);
  509. if (offset != expected_offset) {
  510. ok = false;
  511. }
  512. int64_t ne = shape[0];
  513. for (size_t j = 1; j < GGML_MAX_DIMS; ++j) {
  514. ne *= shape[j];
  515. }
  516. expected_offset += GGML_PAD(ggml_row_size(type, ne), alignment);
  517. }
  518. return ok;
  519. }
  520. static bool handcrafted_check_tensor_data(const gguf_context * gguf_ctx, const unsigned int seed, FILE * file) {
  521. if (!gguf_ctx) {
  522. return false;
  523. }
  524. std::mt19937 rng(seed);
  525. std::vector<tensor_config_t> tensor_configs = get_tensor_configs(rng);
  526. bool ok = true;
  527. for (int i = 0; i < int(tensor_configs.size()); ++i) {
  528. const ggml_type type = tensor_configs[i].first;
  529. const std::array<int64_t, GGML_MAX_DIMS> shape = tensor_configs[i].second;
  530. int64_t ne = shape[0];
  531. for (size_t j = 1; j < GGML_MAX_DIMS; ++j) {
  532. ne *= shape[j];
  533. }
  534. const size_t size = ggml_row_size(type, ne);
  535. const std::string name = "my_tensor_" + std::to_string(i);
  536. const size_t offset = gguf_get_tensor_offset(gguf_ctx, gguf_find_tensor(gguf_ctx, name.c_str()));
  537. std::vector<uint8_t> data(size);
  538. GGML_ASSERT(fseek(file, gguf_get_data_offset(gguf_ctx) + offset, SEEK_SET) == 0);
  539. GGML_ASSERT(fread(data.data(), 1, data.size(), file) == data.size());
  540. for (size_t j = 0; j < size; ++j) {
  541. const uint8_t expected_byte = (j + offset) % 256;
  542. if (data[j] != expected_byte) {
  543. ok = false;
  544. }
  545. }
  546. }
  547. return ok;
  548. }
  549. static std::pair<int, int> test_handcrafted_file(const unsigned int seed) {
  550. int npass = 0;
  551. int ntest = 0;
  552. const std::vector<handcrafted_file_type> hfts = {
  553. HANDCRAFTED_HEADER_BAD_MAGIC,
  554. HANDCRAFTED_HEADER_BAD_VERSION_0,
  555. HANDCRAFTED_HEADER_BAD_VERSION_1,
  556. HANDCRAFTED_HEADER_BAD_VERSION_FUTURE,
  557. HANDCRAFTED_HEADER_BAD_N_KV,
  558. HANDCRAFTED_HEADER_BAD_N_TENSORS,
  559. HANDCRAFTED_HEADER_EMPTY,
  560. HANDCRAFTED_KV_BAD_KEY_SIZE,
  561. HANDCRAFTED_KV_BAD_TYPE,
  562. HANDCRAFTED_KV_DUPLICATE_KEY,
  563. HANDCRAFTED_KV_BAD_ALIGN,
  564. HANDCRAFTED_KV_SUCCESS,
  565. HANDCRAFTED_TENSORS_BAD_NAME_SIZE,
  566. HANDCRAFTED_TENSORS_BAD_N_DIMS,
  567. HANDCRAFTED_TENSORS_BAD_SHAPE,
  568. HANDCRAFTED_TENSORS_NE_TOO_BIG,
  569. HANDCRAFTED_TENSORS_BAD_TYPE,
  570. HANDCRAFTED_TENSORS_BAD_OFFSET,
  571. HANDCRAFTED_TENSORS_DUPLICATE_NAME,
  572. HANDCRAFTED_TENSORS_BAD_ALIGN,
  573. HANDCRAFTED_TENSORS_INCONSISTENT_ALIGN,
  574. HANDCRAFTED_TENSORS_SUCCESS,
  575. HANDCRAFTED_TENSORS_CUSTOM_ALIGN,
  576. HANDCRAFTED_DATA_NOT_ENOUGH_DATA,
  577. HANDCRAFTED_DATA_BAD_ALIGN,
  578. HANDCRAFTED_DATA_INCONSISTENT_ALIGN,
  579. HANDCRAFTED_DATA_SUCCESS,
  580. HANDCRAFTED_DATA_CUSTOM_ALIGN,
  581. };
  582. for (enum handcrafted_file_type hft : hfts) {
  583. printf("%s: handcrafted_file_type=%s\n", __func__, handcrafted_file_type_name(hft).c_str());
  584. FILE * file = get_handcrafted_file(seed, hft);
  585. #ifdef _WIN32
  586. if (!file) {
  587. printf("failed to create tmpfile(), needs elevated privileges on Windows");
  588. printf("skipping tests");
  589. continue;
  590. }
  591. #else
  592. GGML_ASSERT(file);
  593. #endif // _WIN32
  594. struct ggml_context * ctx = nullptr;
  595. struct gguf_init_params gguf_params = {
  596. /*no_alloc =*/ false,
  597. /*ctx =*/ hft >= offset_has_data ? &ctx : nullptr,
  598. };
  599. struct gguf_context * gguf_ctx = gguf_init_from_file_impl(file, gguf_params);
  600. if (expect_context_not_null(hft)) {
  601. printf("%s: - context_not_null: ", __func__);
  602. } else {
  603. printf("%s: - context_null: ", __func__);
  604. }
  605. if (bool(gguf_ctx) == expect_context_not_null(hft)) {
  606. printf("\033[1;32mOK\033[0m\n");
  607. npass++;
  608. } else {
  609. printf("\033[1;31mFAIL\033[0m\n");
  610. }
  611. ntest++;
  612. if (hft >= offset_has_data && !expect_context_not_null(hft)) {
  613. printf("%s: - no_dangling_ggml_context_pointer: ", __func__);
  614. if (ctx) {
  615. printf("\033[1;31mFAIL\033[0m\n");
  616. } else {
  617. printf("\033[1;32mOK\033[0m\n");
  618. npass++;
  619. }
  620. ntest++;
  621. }
  622. const bool alignment_defined = hft == HANDCRAFTED_TENSORS_CUSTOM_ALIGN || hft == HANDCRAFTED_DATA_CUSTOM_ALIGN;
  623. if (expect_context_not_null(hft)) {
  624. printf("%s: - check_header: ", __func__);
  625. if (handcrafted_check_header(gguf_ctx, seed, hft >= offset_has_kv, hft >= offset_has_tensors, alignment_defined)) {
  626. printf("\033[1;32mOK\033[0m\n");
  627. npass++;
  628. } else {
  629. printf("\033[1;31mFAIL\033[0m\n");
  630. }
  631. ntest++;
  632. }
  633. if (expect_context_not_null(hft) && hft >= offset_has_kv) {
  634. printf("%s: - check_kv: ", __func__);
  635. if (handcrafted_check_kv(gguf_ctx, seed, hft >= offset_has_tensors, alignment_defined)) {
  636. printf("\033[1;32mOK\033[0m\n");
  637. npass++;
  638. } else {
  639. printf("\033[1;31mFAIL\033[0m\n");
  640. }
  641. ntest++;
  642. }
  643. if (expect_context_not_null(hft) && hft >= offset_has_tensors) {
  644. printf("%s: - check_tensors: ", __func__);
  645. if (handcrafted_check_tensors(gguf_ctx, seed)) {
  646. printf("\033[1;32mOK\033[0m\n");
  647. npass++;
  648. } else {
  649. printf("\033[1;31mFAIL\033[0m\n");
  650. }
  651. ntest++;
  652. }
  653. if (expect_context_not_null(hft) && hft >= offset_has_data) {
  654. printf("%s: - check_tensor_data: ", __func__);
  655. if (handcrafted_check_tensor_data(gguf_ctx, seed, file)) {
  656. printf("\033[1;32mOK\033[0m\n");
  657. npass++;
  658. } else {
  659. printf("\033[1;31mFAIL\033[0m\n");
  660. }
  661. ntest++;
  662. }
  663. fclose(file);
  664. if (gguf_ctx) {
  665. ggml_free(ctx);
  666. gguf_free(gguf_ctx);
  667. }
  668. printf("\n");
  669. }
  670. return std::make_pair(npass, ntest);
  671. }
  672. struct random_gguf_context_result {
  673. struct gguf_context * gguf_ctx;
  674. struct ggml_context * ctx;
  675. ggml_backend_buffer_t buffer;
  676. };
  677. static struct random_gguf_context_result get_random_gguf_context(ggml_backend_t backend, const unsigned int seed) {
  678. std::mt19937 rng(seed);
  679. struct gguf_context * gguf_ctx = gguf_init_empty();
  680. for (int i = 0; i < 256; ++i) {
  681. const std::string key = "my_key_" + std::to_string(rng() % 1024);
  682. const enum gguf_type type = gguf_type(rng() % GGUF_TYPE_COUNT);
  683. switch (type) {
  684. case GGUF_TYPE_UINT8: gguf_set_val_u8 (gguf_ctx, key.c_str(), rng() % (1 << 7)); break;
  685. case GGUF_TYPE_INT8: gguf_set_val_i8 (gguf_ctx, key.c_str(), rng() % (1 << 7) - (1 << 6)); break;
  686. case GGUF_TYPE_UINT16: gguf_set_val_u16 (gguf_ctx, key.c_str(), rng() % (1 << 15)); break;
  687. case GGUF_TYPE_INT16: gguf_set_val_i16 (gguf_ctx, key.c_str(), rng() % (1 << 15) - (1 << 14)); break;
  688. case GGUF_TYPE_UINT32: gguf_set_val_u32 (gguf_ctx, key.c_str(), rng()); break;
  689. case GGUF_TYPE_INT32: gguf_set_val_i32 (gguf_ctx, key.c_str(), rng() - (1 << 30)); break;
  690. case GGUF_TYPE_FLOAT32: gguf_set_val_f32 (gguf_ctx, key.c_str(), rng() % 1024 - 512); break;
  691. case GGUF_TYPE_BOOL: gguf_set_val_bool(gguf_ctx, key.c_str(), rng() % 2 == 0); break;
  692. case GGUF_TYPE_STRING: gguf_set_val_str (gguf_ctx, key.c_str(), std::to_string(rng()).c_str()); break;
  693. case GGUF_TYPE_UINT64: gguf_set_val_u64 (gguf_ctx, key.c_str(), rng()); break;
  694. case GGUF_TYPE_INT64: gguf_set_val_i64 (gguf_ctx, key.c_str(), rng() - (1 << 30)); break;
  695. case GGUF_TYPE_FLOAT64: gguf_set_val_f32 (gguf_ctx, key.c_str(), rng() % 1024 - 512); break;
  696. case GGUF_TYPE_ARRAY: {
  697. const enum gguf_type type_arr = gguf_type(rng() % GGUF_TYPE_COUNT);
  698. const uint64_t ne = rng() % 1024;
  699. switch (type_arr) {
  700. case GGUF_TYPE_UINT8:
  701. case GGUF_TYPE_INT8:
  702. case GGUF_TYPE_UINT16:
  703. case GGUF_TYPE_INT16:
  704. case GGUF_TYPE_UINT32:
  705. case GGUF_TYPE_INT32:
  706. case GGUF_TYPE_FLOAT32:
  707. case GGUF_TYPE_BOOL:
  708. case GGUF_TYPE_UINT64:
  709. case GGUF_TYPE_INT64:
  710. case GGUF_TYPE_FLOAT64: {
  711. const size_t nbytes = ne*gguf_type_size(type_arr);
  712. std::vector<uint32_t> random_data((nbytes + sizeof(uint32_t) - 1) / sizeof(uint32_t));
  713. for (size_t j = 0; j < random_data.size(); ++j) {
  714. random_data[j] = rng();
  715. if (type_arr == GGUF_TYPE_BOOL) {
  716. random_data[j] &= 0x01010101; // the sanitizer complains if booleans are not 0 or 1
  717. }
  718. }
  719. gguf_set_arr_data(gguf_ctx, key.c_str(), type_arr, random_data.data(), ne);
  720. } break;
  721. case GGUF_TYPE_STRING: {
  722. std::vector<std::string> data_cpp(ne);
  723. std::vector<const char *> data_c(ne);
  724. for (size_t j = 0; j < data_cpp.size(); ++j) {
  725. data_cpp[j] = std::to_string(rng());
  726. data_c[j] = data_cpp[j].c_str();
  727. }
  728. gguf_set_arr_str(gguf_ctx, key.c_str(), data_c.data(), ne);
  729. } break;
  730. case GGUF_TYPE_ARRAY: {
  731. break; // not supported
  732. }
  733. case GGUF_TYPE_COUNT:
  734. default: {
  735. GGML_ABORT("fatal error");
  736. }
  737. }
  738. } break;
  739. case GGUF_TYPE_COUNT:
  740. default: {
  741. GGML_ABORT("fatal error");
  742. }
  743. }
  744. }
  745. struct ggml_init_params ggml_params = {
  746. /*.mem_size =*/ 256*ggml_tensor_overhead(),
  747. /*.mem_buffer =*/ nullptr,
  748. /*.no_alloc =*/ true,
  749. };
  750. struct ggml_context * ctx = ggml_init(ggml_params);
  751. for (int i = 0; i < 256; ++i) {
  752. const std::string name = "my_tensor_" + std::to_string(i);
  753. const enum ggml_type type = ggml_type(rng() % GGML_TYPE_COUNT);
  754. const size_t type_size = ggml_type_size(type);
  755. if (type_size == 0) {
  756. continue;
  757. }
  758. const int n_dims = 1 + rng() % GGML_MAX_DIMS;
  759. int64_t ne[GGML_MAX_DIMS];
  760. ne[0] = (1 + rng() % 10) * ggml_blck_size(type);
  761. for (int j = 1; j < n_dims; ++j) {
  762. ne[j] = 1 + rng() % 10;
  763. }
  764. struct ggml_tensor * tensor = ggml_new_tensor(ctx, type, n_dims, ne);
  765. ggml_set_name(tensor, name.c_str());
  766. }
  767. ggml_backend_buffer_t buf = ggml_backend_alloc_ctx_tensors(ctx, backend);
  768. for (struct ggml_tensor * t = ggml_get_first_tensor(ctx); t != nullptr; t = ggml_get_next_tensor(ctx, t)) {
  769. const size_t nbytes = ggml_nbytes(t);
  770. std::vector<uint32_t> random_data((nbytes + sizeof(uint32_t) - 1) / sizeof(uint32_t));
  771. for (size_t j = 0; j < random_data.size(); ++j) {
  772. random_data[j] = rng();
  773. }
  774. ggml_backend_tensor_set(t, random_data.data(), 0, nbytes);
  775. gguf_add_tensor(gguf_ctx, t);
  776. }
  777. return {gguf_ctx, ctx, buf};
  778. }
  779. static bool all_kv_in_other(const gguf_context * ctx, const gguf_context * other) {
  780. bool ok = true;
  781. const int n_kv = gguf_get_n_kv(ctx);
  782. for (int id = 0; id < n_kv; ++id) {
  783. const char * name = gguf_get_key(ctx, id);
  784. const int idx_other = gguf_find_key(other, name);
  785. if (idx_other < 0) {
  786. ok = false;
  787. continue;
  788. }
  789. const gguf_type type = gguf_get_kv_type(ctx, id);
  790. if (type != gguf_get_kv_type(other, idx_other)) {
  791. ok = false;
  792. continue;
  793. }
  794. if (type == GGUF_TYPE_ARRAY) {
  795. const size_t arr_n = gguf_get_arr_n(ctx, id);
  796. if (arr_n != gguf_get_arr_n(other, idx_other)) {
  797. ok = false;
  798. continue;
  799. }
  800. const gguf_type type_arr = gguf_get_arr_type(ctx, id);
  801. if (type_arr != gguf_get_arr_type(other, idx_other)) {
  802. ok = false;
  803. continue;
  804. }
  805. if (type_arr == GGUF_TYPE_BOOL) {
  806. const int8_t * data = reinterpret_cast<const int8_t *>(gguf_get_arr_data(ctx, id));
  807. const int8_t * data_other = reinterpret_cast<const int8_t *>(gguf_get_arr_data(other, idx_other));
  808. for (size_t arr_i = 0; arr_i < arr_n; ++arr_i) {
  809. if (bool(data[arr_i]) != bool(data_other[arr_i])) {
  810. ok = false;
  811. }
  812. }
  813. continue;
  814. }
  815. if (type_arr == GGUF_TYPE_STRING) {
  816. for (size_t arr_i = 0; arr_i < arr_n; ++arr_i) {
  817. const std::string str = gguf_get_arr_str(ctx, id, arr_i);
  818. const std::string str_other = gguf_get_arr_str(other, idx_other, arr_i);
  819. if (str != str_other) {
  820. ok = false;
  821. }
  822. }
  823. continue;
  824. }
  825. const int8_t * data = reinterpret_cast<const int8_t *>(gguf_get_arr_data(ctx, id));
  826. const int8_t * data_other = reinterpret_cast<const int8_t *>(gguf_get_arr_data(other, idx_other));
  827. if (!std::equal(data, data + arr_n*gguf_type_size(type_arr), data_other)) {
  828. ok = false;
  829. }
  830. continue;
  831. }
  832. if (type == GGUF_TYPE_STRING) {
  833. const std::string str = gguf_get_val_str(ctx, id);
  834. const std::string str_other = gguf_get_val_str(other, idx_other);
  835. if (str != str_other) {
  836. ok = false;
  837. }
  838. continue;
  839. }
  840. const char * data = reinterpret_cast<const char *>(gguf_get_val_data(ctx, id));
  841. const char * data_other = reinterpret_cast<const char *>(gguf_get_val_data(other, idx_other));
  842. if (!std::equal(data, data + gguf_type_size(type), data_other)) {
  843. ok = false;
  844. }
  845. }
  846. return ok;
  847. }
  848. static bool all_tensors_in_other(const gguf_context * ctx, const gguf_context * other) {
  849. bool ok = true;
  850. const int n_tensors = gguf_get_n_tensors(ctx);
  851. for (int id = 0; id < n_tensors; ++id) {
  852. const std::string name = gguf_get_tensor_name(ctx, id);
  853. const int idx_other = gguf_find_tensor(other, name.c_str());
  854. if (id != idx_other) {
  855. ok = false;
  856. if (idx_other < 0) {
  857. continue;
  858. }
  859. }
  860. const ggml_type type = gguf_get_tensor_type(ctx, id);
  861. if (type != gguf_get_tensor_type(other, id)) {
  862. ok = false;
  863. }
  864. const size_t offset = gguf_get_tensor_offset(ctx, id);
  865. if (offset != gguf_get_tensor_offset(other, id)) {
  866. ok = false;
  867. }
  868. }
  869. return ok;
  870. }
  871. static bool same_tensor_data(const struct ggml_context * orig, const struct ggml_context * read) {
  872. bool ok = true;
  873. struct ggml_tensor * t_orig = ggml_get_first_tensor(orig);
  874. struct ggml_tensor * t_read = ggml_get_first_tensor(read);
  875. if (std::string(t_read->name) != "GGUF tensor data binary blob") {
  876. return false;
  877. }
  878. t_read = ggml_get_next_tensor(read, t_read);
  879. while (t_orig) {
  880. if (!t_read) {
  881. ok = false;
  882. break;
  883. }
  884. const size_t nbytes = ggml_nbytes(t_orig);
  885. if (ggml_nbytes(t_read) != nbytes) {
  886. ok = false;
  887. break;
  888. }
  889. std::vector<char> data_orig(nbytes);
  890. ggml_backend_tensor_get(t_orig, data_orig.data(), 0, nbytes);
  891. if (!std::equal(data_orig.data(), data_orig.data() + nbytes, reinterpret_cast<const char *>(t_read->data))) {
  892. ok = false;
  893. }
  894. t_orig = ggml_get_next_tensor(orig, t_orig);
  895. t_read = ggml_get_next_tensor(read, t_read);
  896. }
  897. if (t_read) {
  898. ok = false;
  899. }
  900. return ok;
  901. }
  902. static std::pair<int, int> test_roundtrip(ggml_backend_dev_t dev, const unsigned int seed, const bool only_meta) {
  903. ggml_backend_t backend = ggml_backend_dev_init(dev, nullptr);
  904. printf("%s: device=%s, backend=%s, only_meta=%s\n",
  905. __func__, ggml_backend_dev_description(dev), ggml_backend_name(backend), only_meta ? "yes" : "no");
  906. int npass = 0;
  907. int ntest = 0;
  908. struct gguf_context * gguf_ctx_0;
  909. struct ggml_context * ctx_0;
  910. ggml_backend_buffer_t bbuf;
  911. {
  912. struct random_gguf_context_result result = get_random_gguf_context(backend, seed);
  913. gguf_ctx_0 = result.gguf_ctx;
  914. ctx_0 = result.ctx;
  915. bbuf = result.buffer;
  916. }
  917. FILE * file = tmpfile();
  918. #ifdef _WIN32
  919. if (!file) {
  920. printf("failed to create tmpfile(), needs elevated privileges on Windows");
  921. printf("skipping tests");
  922. return std::make_pair(0, 0);
  923. }
  924. #else
  925. GGML_ASSERT(file);
  926. #endif // _WIN32
  927. {
  928. std::vector<int8_t> buf;
  929. gguf_write_to_buf(gguf_ctx_0, buf, only_meta);
  930. GGML_ASSERT(fwrite(buf.data(), 1, buf.size(), file) == buf.size());
  931. rewind(file);
  932. }
  933. struct ggml_context * ctx_1 = nullptr;
  934. struct gguf_init_params gguf_params = {
  935. /*no_alloc =*/ false,
  936. /*ctx =*/ only_meta ? nullptr : &ctx_1,
  937. };
  938. struct gguf_context * gguf_ctx_1 = gguf_init_from_file_impl(file, gguf_params);
  939. printf("%s: same_version: ", __func__);
  940. if (gguf_get_version(gguf_ctx_0) == gguf_get_version(gguf_ctx_1)) {
  941. printf("\033[1;32mOK\033[0m\n");
  942. npass++;
  943. } else {
  944. printf("\033[1;31mFAIL\033[0m\n");
  945. }
  946. ntest++;
  947. printf("%s: same_n_kv: ", __func__);
  948. if (gguf_get_n_kv(gguf_ctx_0) == gguf_get_n_kv(gguf_ctx_1)) {
  949. printf("\033[1;32mOK\033[0m\n");
  950. npass++;
  951. } else {
  952. printf("\033[1;31mFAIL\033[0m\n");
  953. }
  954. ntest++;
  955. printf("%s: same_n_tensors: ", __func__);
  956. if (gguf_get_n_tensors(gguf_ctx_0) == gguf_get_n_tensors(gguf_ctx_1)) {
  957. printf("\033[1;32mOK\033[0m\n");
  958. npass++;
  959. } else {
  960. printf("\033[1;31mFAIL\033[0m\n");
  961. }
  962. ntest++;
  963. printf("%s: all_orig_kv_in_read: ", __func__);
  964. if (all_kv_in_other(gguf_ctx_0, gguf_ctx_1)) {
  965. printf("\033[1;32mOK\033[0m\n");
  966. npass++;
  967. } else {
  968. printf("\033[1;31mFAIL\033[0m\n");
  969. }
  970. ntest++;
  971. printf("%s: all_read_kv_in_orig: ", __func__);
  972. if (all_kv_in_other(gguf_ctx_1, gguf_ctx_0)) {
  973. printf("\033[1;32mOK\033[0m\n");
  974. npass++;
  975. } else {
  976. printf("\033[1;31mFAIL\033[0m\n");
  977. }
  978. ntest++;
  979. printf("%s: all_orig_tensors_in_read: ", __func__);
  980. if (all_tensors_in_other(gguf_ctx_0, gguf_ctx_1)) {
  981. printf("\033[1;32mOK\033[0m\n");
  982. npass++;
  983. } else {
  984. printf("\033[1;31mFAIL\033[0m\n");
  985. }
  986. ntest++;
  987. printf("%s: all_read_tensors_in_orig: ", __func__);
  988. if (all_tensors_in_other(gguf_ctx_1, gguf_ctx_0)) {
  989. printf("\033[1;32mOK\033[0m\n");
  990. npass++;
  991. } else {
  992. printf("\033[1;31mFAIL\033[0m\n");
  993. }
  994. ntest++;
  995. if (!only_meta) {
  996. printf("%s: same_tensor_data: ", __func__);
  997. if (same_tensor_data(ctx_0, ctx_1)) {
  998. printf("\033[1;32mOK\033[0m\n");
  999. npass++;
  1000. } else {
  1001. printf("\033[1;31mFAIL\033[0m\n");
  1002. }
  1003. ntest++;
  1004. }
  1005. ggml_backend_buffer_free(bbuf);
  1006. ggml_free(ctx_0);
  1007. ggml_free(ctx_1);
  1008. gguf_free(gguf_ctx_0);
  1009. gguf_free(gguf_ctx_1);
  1010. ggml_backend_free(backend);
  1011. fclose(file);
  1012. printf("\n");
  1013. return std::make_pair(npass, ntest);
  1014. }
  1015. static std::pair<int, int> test_gguf_set_kv(ggml_backend_dev_t dev, const unsigned int seed) {
  1016. ggml_backend_t backend = ggml_backend_dev_init(dev, nullptr);
  1017. printf("%s: device=%s, backend=%s\n", __func__, ggml_backend_dev_description(dev), ggml_backend_name(backend));
  1018. int npass = 0;
  1019. int ntest = 0;
  1020. struct gguf_context * gguf_ctx_0;
  1021. struct ggml_context * ctx_0;
  1022. ggml_backend_buffer_t bbuf_0;
  1023. {
  1024. struct random_gguf_context_result result = get_random_gguf_context(backend, seed);
  1025. gguf_ctx_0 = result.gguf_ctx;
  1026. ctx_0 = result.ctx;
  1027. bbuf_0 = result.buffer;
  1028. }
  1029. struct gguf_context * gguf_ctx_1;
  1030. struct ggml_context * ctx_1;
  1031. ggml_backend_buffer_t bbuf_1;
  1032. {
  1033. struct random_gguf_context_result result = get_random_gguf_context(backend, seed + 1);
  1034. gguf_ctx_1 = result.gguf_ctx;
  1035. ctx_1 = result.ctx;
  1036. bbuf_1 = result.buffer;
  1037. }
  1038. struct gguf_context * gguf_ctx_2 = gguf_init_empty();
  1039. gguf_set_kv(gguf_ctx_1, gguf_ctx_0);
  1040. gguf_set_kv(gguf_ctx_2, gguf_ctx_0);
  1041. printf("%s: same_n_kv: ", __func__);
  1042. if (gguf_get_n_kv(gguf_ctx_0) == gguf_get_n_kv(gguf_ctx_2)) {
  1043. printf("\033[1;32mOK\033[0m\n");
  1044. npass++;
  1045. } else {
  1046. printf("\033[1;31mFAIL\033[0m\n");
  1047. }
  1048. ntest++;
  1049. printf("%s: all_kv_0_in_1: ", __func__);
  1050. if (all_kv_in_other(gguf_ctx_0, gguf_ctx_1)) {
  1051. printf("\033[1;32mOK\033[0m\n");
  1052. npass++;
  1053. } else {
  1054. printf("\033[1;31mFAIL\033[0m\n");
  1055. }
  1056. ntest++;
  1057. printf("%s: all_kv_0_in_2: ", __func__);
  1058. if (all_kv_in_other(gguf_ctx_0, gguf_ctx_2)) {
  1059. printf("\033[1;32mOK\033[0m\n");
  1060. npass++;
  1061. } else {
  1062. printf("\033[1;31mFAIL\033[0m\n");
  1063. }
  1064. ntest++;
  1065. gguf_set_kv(gguf_ctx_0, gguf_ctx_1);
  1066. printf("%s: same_n_kv_after_double_copy: ", __func__);
  1067. if (gguf_get_n_kv(gguf_ctx_0) == gguf_get_n_kv(gguf_ctx_1)) {
  1068. printf("\033[1;32mOK\033[0m\n");
  1069. npass++;
  1070. } else {
  1071. printf("\033[1;31mFAIL\033[0m\n");
  1072. }
  1073. ntest++;
  1074. printf("%s: all_kv_1_in_0_after_double_copy: ", __func__);
  1075. if (all_kv_in_other(gguf_ctx_1, gguf_ctx_0)) {
  1076. printf("\033[1;32mOK\033[0m\n");
  1077. npass++;
  1078. } else {
  1079. printf("\033[1;31mFAIL\033[0m\n");
  1080. }
  1081. ntest++;
  1082. ggml_backend_buffer_free(bbuf_0);
  1083. ggml_backend_buffer_free(bbuf_1);
  1084. ggml_free(ctx_0);
  1085. ggml_free(ctx_1);
  1086. gguf_free(gguf_ctx_0);
  1087. gguf_free(gguf_ctx_1);
  1088. gguf_free(gguf_ctx_2);
  1089. ggml_backend_free(backend);
  1090. printf("\n");
  1091. return std::make_pair(npass, ntest);
  1092. }
  1093. static void print_usage() {
  1094. printf("usage: test-gguf [seed]\n");
  1095. printf(" if no seed is unspecified then a random seed is used\n");
  1096. }
  1097. int main(int argc, char ** argv) {
  1098. if (argc > 2) {
  1099. print_usage();
  1100. return 1;
  1101. }
  1102. std::random_device rd;
  1103. const unsigned int seed = argc < 2 ? rd() : std::stoi(argv[1]);
  1104. // Initialize ggml backends early so the prints aren't interleaved with the test results:
  1105. ggml_backend_dev_count();
  1106. fprintf(stderr, "\n");
  1107. int npass = 0;
  1108. int ntest = 0;
  1109. {
  1110. std::pair<int, int> result = test_handcrafted_file(seed);
  1111. npass += result.first;
  1112. ntest += result.second;
  1113. }
  1114. for (size_t i = 0; i < ggml_backend_dev_count(); ++i) {
  1115. ggml_backend_dev_t dev = ggml_backend_dev_get(i);
  1116. for (bool only_meta : {true, false}) {
  1117. std::pair<int, int> result = test_roundtrip(dev, seed, only_meta);
  1118. npass += result.first;
  1119. ntest += result.second;
  1120. }
  1121. {
  1122. std::pair<int, int> result = test_gguf_set_kv(dev, seed);
  1123. npass += result.first;
  1124. ntest += result.second;
  1125. }
  1126. }
  1127. printf("%d/%d tests passed\n", npass, ntest);
  1128. if (npass != ntest) {
  1129. printf("\033[1;31mFAIL\033[0m\n");
  1130. return 1;
  1131. }
  1132. printf("\033[1;32mOK\033[0m\n");
  1133. return 0;
  1134. }