package adminapi import ( "bytes" "encoding/binary" "net/http" "net/http/httptest" "strings" "testing" "gitea.mynodes.xyz/ilker/llmgw/internal/control/catalog" ) // ggufStart is the start of a GGUF file with these string keys. func ggufStart(kv ...string) []byte { var b bytes.Buffer w := func(v any) { _ = binary.Write(&b, binary.LittleEndian, v) } str := func(s string) { w(uint64(len(s))); b.WriteString(s) } b.WriteString("GGUF") w(uint32(3)) w(uint64(0)) w(uint64(len(kv) / 2)) for i := 0; i < len(kv); i += 2 { str(kv[i]) w(uint32(8)) // string str(kv[i+1]) } b.Write(make([]byte, 4096)) return b.Bytes() } func TestOnlyAnAdapterForTheModelsArchitectureIsAttached(t *testing.T) { files := map[string][]byte{ "/base.gguf": ggufStart("general.architecture", "qwen2"), "/model.gguf": ggufStart("general.architecture", "qwen2", "general.type", "model"), "/llama.gguf": ggufStart("general.architecture", "llama", "general.type", "adapter"), "/lora.gguf": ggufStart("general.architecture", "qwen2", "general.type", "adapter"), } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusPartialContent) _, _ = w.Write(files[r.URL.Path]) })) defer srv.Close() models := []catalog.Model{{ Name: "coder", Source: srv.URL + "/base.gguf", Scaling: catalog.Scaling{Min: 1, Max: 1}, Profiles: []catalog.Profile{{Name: "cpu", Engine: "llamacpp", MinMemoryGB: 8}}, }} for _, tc := range []struct { file, want string code int }{ {"/model.gguf", "not a LoRA adapter", http.StatusBadRequest}, {"/llama.gguf", "for llama models", http.StatusBadRequest}, {"/lora.gguf", "", http.StatusOK}, } { a, _ := setup(t, models) fm := &fakeModels{} a.SetModels(fm) mux := http.NewServeMux() a.Register(mux) req := httptest.NewRequest(http.MethodPost, "/api/v1/models/coder/adapters", strings.NewReader(`{"adapters":[{"name":"fix","source":"`+srv.URL+tc.file+`"}]}`)) rec := httptest.NewRecorder() mux.ServeHTTP(rec, req) if rec.Code != tc.code || !strings.Contains(rec.Body.String(), tc.want) { t.Errorf("%s: %d %s; want %d mentioning %q", tc.file, rec.Code, rec.Body.String(), tc.code, tc.want) } } }