CoolFace
Modelpublic

Codeprocastinator/optimized-tinyllama-covalent

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

Showing the first 1,200 of 1339 lines. Download the file for the rest.