@@ -27,6 +27,7 @@ import (
2727type mockDB struct {
2828 database.Querier // nil — panics if an unexpected method is called
2929
30+ insertKnowledge func (ctx context.Context , arg database.InsertKnowledgeDocumentParams ) (string , error )
3031 getKnowledge func (ctx context.Context , uuid string ) (database.GetKnowledgeDocumentRow , error )
3132 getUserKnowledge func (ctx context.Context , arg database.GetUserKnowledgeDocumentParams ) (database.GetUserKnowledgeDocumentRow , error )
3233 listAll func (ctx context.Context ) ([]database.ListAllKnowledgeDocumentsRow , error )
@@ -39,6 +40,9 @@ type mockDB struct {
3940 searchUserKnowledge func (ctx context.Context , arg database.SearchUserKnowledgeDocumentsParams ) ([]database.SearchUserKnowledgeDocumentsRow , error )
4041}
4142
43+ func (m * mockDB ) InsertKnowledgeDocument (ctx context.Context , arg database.InsertKnowledgeDocumentParams ) (string , error ) {
44+ return m .insertKnowledge (ctx , arg )
45+ }
4246func (m * mockDB ) GetKnowledgeDocument (ctx context.Context , uuid string ) (database.GetKnowledgeDocumentRow , error ) {
4347 return m .getKnowledge (ctx , uuid )
4448}
@@ -1437,56 +1441,100 @@ func TestCreateDocument(t *testing.T) {
14371441 ctx := context .Background ()
14381442 const userID = int64 (11 )
14391443
1440- t .Run ("store nil returns error immediately" , func (t * testing.T ) {
1441- ks := & knowledgeStore {store : nil }
1444+ // insertOK returns a mockDB whose InsertKnowledgeDocument returns a fixed id.
1445+ insertOK := func (id string ) * mockDB {
1446+ return & mockDB {
1447+ insertKnowledge : func (_ context.Context , _ database.InsertKnowledgeDocumentParams ) (string , error ) {
1448+ return id , nil
1449+ },
1450+ }
1451+ }
1452+
1453+ t .Run ("embedder nil returns error" , func (t * testing.T ) {
1454+ ks := & knowledgeStore {db : insertOK ("id" ), embedder : nil }
1455+ _ , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
1456+ DocType : model .KnowledgeDocTypeAnswer , Content : "x" , Question : "q" ,
1457+ })
1458+ if err == nil {
1459+ t .Fatal ("expected error when embedder is nil" )
1460+ }
1461+ })
1462+
1463+ t .Run ("embedder unavailable returns error" , func (t * testing.T ) {
1464+ ks := & knowledgeStore {db : insertOK ("id" ), embedder : & mockEmbedder {available : false }}
14421465 _ , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
14431466 DocType : model .KnowledgeDocTypeAnswer , Content : "x" , Question : "q" ,
14441467 })
14451468 if err == nil {
1446- t .Fatal ("expected error when store is nil " )
1469+ t .Fatal ("expected error when embedder unavailable " )
14471470 }
14481471 })
14491472
1450- t .Run ("store AddDocuments error propagates" , func (t * testing.T ) {
1451- vs := & mockVectorStore {
1452- addDocumentsFn : func (_ context.Context , _ []schema.Document , _ ... vectorstores.Option ) ([]string , error ) {
1453- return nil , errors .New ("vector db error" )
1473+ t .Run ("EmbedDocuments error propagates" , func (t * testing.T ) {
1474+ ks := & knowledgeStore {
1475+ db : insertOK ("id" ),
1476+ embedder : & mockEmbedder {
1477+ available : true ,
1478+ embedDocumentsFn : func (_ context.Context , _ []string ) ([][]float32 , error ) {
1479+ return nil , errors .New ("embed error" )
1480+ },
14541481 },
14551482 }
1456- ks := & knowledgeStore {store : vs , newKnp : newPublisherFactory (& mockPublisher {})}
14571483 _ , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
14581484 DocType : model .KnowledgeDocTypeGuide , Content : "c" , Question : "q" ,
14591485 })
14601486 if err == nil {
1461- t .Fatal ("expected error from AddDocuments " )
1487+ t .Fatal ("expected error from EmbedDocuments " )
14621488 }
14631489 })
14641490
1465- t .Run ("AddDocuments returning no IDs is an error" , func (t * testing.T ) {
1466- vs := & mockVectorStore {
1467- addDocumentsFn : func (_ context.Context , _ []schema.Document , _ ... vectorstores.Option ) ([]string , error ) {
1468- return []string {}, nil // empty slice
1491+ t .Run ("embedder returning empty vectors is an error" , func (t * testing.T ) {
1492+ ks := & knowledgeStore {
1493+ db : insertOK ("id" ),
1494+ embedder : & mockEmbedder {
1495+ available : true ,
1496+ embedDocumentsFn : func (_ context.Context , _ []string ) ([][]float32 , error ) {
1497+ return [][]float32 {}, nil // empty slice
1498+ },
14691499 },
14701500 }
1471- ks := & knowledgeStore {store : vs , newKnp : newPublisherFactory (& mockPublisher {})}
14721501 _ , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
14731502 DocType : model .KnowledgeDocTypeAnswer , Content : "c" , Question : "q" ,
14741503 })
14751504 if err == nil {
1476- t .Fatal ("expected error for empty IDs" )
1505+ t .Fatal ("expected error for empty vectors" )
1506+ }
1507+ })
1508+
1509+ t .Run ("db insert error propagates" , func (t * testing.T ) {
1510+ db := & mockDB {
1511+ insertKnowledge : func (_ context.Context , _ database.InsertKnowledgeDocumentParams ) (string , error ) {
1512+ return "" , errors .New ("constraint error" )
1513+ },
1514+ }
1515+ ks := & knowledgeStore {
1516+ db : db ,
1517+ embedder : & mockEmbedder {available : true },
1518+ newKnp : newPublisherFactory (& mockPublisher {}),
1519+ }
1520+ _ , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
1521+ DocType : model .KnowledgeDocTypeAnswer , Content : "c" , Question : "q" ,
1522+ })
1523+ if err == nil {
1524+ t .Fatal ("expected error from db insert" )
14771525 }
14781526 })
14791527
14801528 t .Run ("success: all fields set, manual=true, user_id present, event published" , func (t * testing.T ) {
14811529 pub := & mockPublisher {}
1482- var capturedDocs []schema. Document
1483- vs := & mockVectorStore {
1484- addDocumentsFn : func (_ context.Context , docs []schema. Document , _ ... vectorstores. Option ) ([] string , error ) {
1485- capturedDocs = docs
1486- return [] string { "new-uuid" } , nil
1530+ var gotParams database. InsertKnowledgeDocumentParams
1531+ db := & mockDB {
1532+ insertKnowledge : func (_ context.Context , arg database. InsertKnowledgeDocumentParams ) (string , error ) {
1533+ gotParams = arg
1534+ return "new-uuid" , nil
14871535 },
14881536 }
1489- ks := & knowledgeStore {store : vs , newKnp : newPublisherFactory (pub )}
1537+ ks := & knowledgeStore {db : db , embedder : & mockEmbedder { available : true } , newKnp : newPublisherFactory (pub )}
14901538
14911539 input := model.CreateKnowledgeDocumentInput {
14921540 DocType : model .KnowledgeDocTypeCode ,
@@ -1510,25 +1558,35 @@ func TestCreateDocument(t *testing.T) {
15101558 if ! doc .Manual {
15111559 t .Fatal ("manual must be true for manually created docs" )
15121560 }
1561+ if doc .UserID != userID {
1562+ t .Fatalf ("doc.UserID: want %d, got %d" , userID , doc .UserID )
1563+ }
1564+ if doc .CodeLang == nil || * doc .CodeLang != "go" {
1565+ t .Fatal ("code_lang missing from returned doc" )
1566+ }
15131567
1514- // Metadata stored in pgvector
1515- if len ( capturedDocs ) != 1 {
1516- t .Fatal ( "expected exactly one document passed to AddDocuments" )
1568+ // Persisted document text (trimmed) and embedding literal
1569+ if gotParams . Document . String != "func main() {}" {
1570+ t .Fatalf ( "persisted document not trimmed: %q" , gotParams . Document . String )
15171571 }
1518- meta := capturedDocs [0 ].Metadata
1519- if meta ["user_id" ] != userID {
1520- t .Fatalf ("user_id in metadata: want %d, got %v" , userID , meta ["user_id" ])
1572+ emb , ok := gotParams .Embedding .(string )
1573+ if ! ok || emb == "" || emb [0 ] != '[' {
1574+ t .Fatalf ("embedding must be a vector literal, got %v" , gotParams .Embedding )
1575+ }
1576+
1577+ // Metadata stored in pgvector cmetadata
1578+ meta := parseMeta (string (gotParams .Cmetadata ))
1579+ if meta .UserID != userID {
1580+ t .Fatalf ("user_id in metadata: want %d, got %d" , userID , meta .UserID )
15211581 }
1522- if meta [ "manual" ] != true {
1582+ if ! meta . Manual {
15231583 t .Fatal ("manual flag must be true in metadata" )
15241584 }
1525- if meta [ "code_lang" ] != "go" {
1585+ if meta . CodeLang != "go" {
15261586 t .Fatal ("code_lang missing from metadata" )
15271587 }
1528-
1529- // Returned model must carry the creator's UserID
1530- if doc .UserID != userID {
1531- t .Fatalf ("doc.UserID: want %d, got %d" , userID , doc .UserID )
1588+ if meta .Description != "a Go main" {
1589+ t .Fatalf ("description missing from metadata: %q" , meta .Description )
15321590 }
15331591
15341592 // Event
@@ -1541,32 +1599,27 @@ func TestCreateDocument(t *testing.T) {
15411599 })
15421600
15431601 t .Run ("content is trimmed of whitespace" , func (t * testing.T ) {
1544- var capturedContent string
1545- vs := & mockVectorStore {
1546- addDocumentsFn : func (_ context.Context , docs []schema. Document , _ ... vectorstores. Option ) ([] string , error ) {
1547- capturedContent = docs [ 0 ]. PageContent
1548- return [] string { "id" } , nil
1602+ var gotParams database. InsertKnowledgeDocumentParams
1603+ db := & mockDB {
1604+ insertKnowledge : func (_ context.Context , arg database. InsertKnowledgeDocumentParams ) (string , error ) {
1605+ gotParams = arg
1606+ return "id" , nil
15491607 },
15501608 }
1551- ks := & knowledgeStore {store : vs , newKnp : newPublisherFactory (& mockPublisher {})}
1609+ ks := & knowledgeStore {db : db , embedder : & mockEmbedder { available : true } , newKnp : newPublisherFactory (& mockPublisher {})}
15521610 _ , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
15531611 DocType : model .KnowledgeDocTypeAnswer , Content : " trimmed " , Question : "q" ,
15541612 })
15551613 if err != nil {
15561614 t .Fatal (err )
15571615 }
1558- if capturedContent != "trimmed" {
1559- t .Fatalf ("expected trimmed content, got %q" , capturedContent )
1616+ if gotParams . Document . String != "trimmed" {
1617+ t .Fatalf ("expected trimmed content, got %q" , gotParams . Document . String )
15601618 }
15611619 })
15621620
15631621 t .Run ("optional fields absent means nil in model" , func (t * testing.T ) {
1564- vs := & mockVectorStore {
1565- addDocumentsFn : func (_ context.Context , _ []schema.Document , _ ... vectorstores.Option ) ([]string , error ) {
1566- return []string {"id" }, nil
1567- },
1568- }
1569- ks := & knowledgeStore {store : vs , newKnp : newPublisherFactory (& mockPublisher {})}
1622+ ks := & knowledgeStore {db : insertOK ("id" ), embedder : & mockEmbedder {available : true }, newKnp : newPublisherFactory (& mockPublisher {})}
15701623 doc , err := ks .CreateDocument (ctx , userID , model.CreateKnowledgeDocumentInput {
15711624 DocType : model .KnowledgeDocTypeAnswer , Content : "c" , Question : "q" ,
15721625 })
0 commit comments