mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-07-17 05:07:23 +08:00
255 lines
7.3 KiB
Go
255 lines
7.3 KiB
Go
//
|
|
// Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
package testutil
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"testing"
|
|
|
|
"ragflow/internal/common"
|
|
"ragflow/internal/dao"
|
|
"ragflow/internal/entity"
|
|
|
|
"github.com/glebarez/sqlite"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
// ──────────────────────────────────────────────────────────
|
|
// Simple Helper Functions
|
|
// ──────────────────────────────────────────────────────────
|
|
|
|
// StrPtr returns a pointer to the given string.
|
|
func StrPtr(s string) *string {
|
|
return &s
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────
|
|
// Database Helpers
|
|
// ──────────────────────────────────────────────────────────
|
|
|
|
// SetupTestDB sets up an in-memory SQLite database for testing.
|
|
// It auto-migrates the given tables (or all common tables if none provided).
|
|
func SetupTestDB(t *testing.T, tables ...any) *gorm.DB {
|
|
t.Helper()
|
|
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", strings.NewReplacer("/", "_", " ", "_").Replace(t.Name()))
|
|
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{
|
|
Logger: logger.Default.LogMode(logger.Silent),
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
sqlDB, err := db.DB()
|
|
if err != nil {
|
|
t.Fatalf("failed to get sql DB: %v", err)
|
|
}
|
|
sqlDB.SetMaxOpenConns(1)
|
|
|
|
if len(tables) == 0 {
|
|
tables = []any{
|
|
&entity.IngestionTask{},
|
|
&entity.IngestionTaskLog{},
|
|
&entity.Task{},
|
|
&entity.Document{},
|
|
&entity.Knowledgebase{},
|
|
&entity.Tenant{},
|
|
&entity.File{},
|
|
&entity.File2Document{},
|
|
}
|
|
}
|
|
|
|
if err := db.AutoMigrate(tables...); err != nil {
|
|
t.Fatalf("auto-migrate: %v", err)
|
|
}
|
|
return db
|
|
}
|
|
|
|
// ReplaceDBForTest replaces dao.DB with the given test database
|
|
// and returns a cleanup function to restore the original.
|
|
func ReplaceDBForTest(t *testing.T, db *gorm.DB) func() {
|
|
t.Helper()
|
|
origDB := dao.DB
|
|
dao.DB = db
|
|
return func() { dao.DB = origDB }
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────
|
|
// Test Data Configuration (Options Pattern)
|
|
// ──────────────────────────────────────────────────────────
|
|
|
|
// TestDataOption configures the test data setup.
|
|
type TestDataOption func(*testDataConfig)
|
|
|
|
type testDataConfig struct {
|
|
tenantID string
|
|
kbID string
|
|
docID string
|
|
taskID string
|
|
pipelineID *string
|
|
docName string
|
|
docType string
|
|
}
|
|
|
|
// WithTenantID sets the tenant ID for test data.
|
|
func WithTenantID(id string) TestDataOption {
|
|
return func(c *testDataConfig) { c.tenantID = id }
|
|
}
|
|
|
|
// WithKBID sets the knowledgebase ID for test data.
|
|
func WithKBID(id string) TestDataOption {
|
|
return func(c *testDataConfig) { c.kbID = id }
|
|
}
|
|
|
|
// WithDocID sets the document ID for test data.
|
|
func WithDocID(id string) TestDataOption {
|
|
return func(c *testDataConfig) { c.docID = id }
|
|
}
|
|
|
|
// WithTaskID sets the task ID for test data.
|
|
func WithTaskID(id string) TestDataOption {
|
|
return func(c *testDataConfig) { c.taskID = id }
|
|
}
|
|
|
|
// WithPipelineID sets the pipeline ID for test data.
|
|
func WithPipelineID(id string) TestDataOption {
|
|
return func(c *testDataConfig) {
|
|
pid := id
|
|
c.pipelineID = &pid
|
|
}
|
|
}
|
|
|
|
// WithDocName sets the document name for test data.
|
|
func WithDocName(name string) TestDataOption {
|
|
return func(c *testDataConfig) { c.docName = name }
|
|
}
|
|
|
|
// WithDocType sets the document type for test data.
|
|
func WithDocType(docType string) TestDataOption {
|
|
return func(c *testDataConfig) { c.docType = docType }
|
|
}
|
|
|
|
// SeedTestData seeds the database with test data.
|
|
// Returns: tenantID, kbID, docID, taskID
|
|
func SeedTestData(t *testing.T, db *gorm.DB, opts ...TestDataOption) (string, string, string, string) {
|
|
t.Helper()
|
|
cfg := &testDataConfig{
|
|
tenantID: "tenant-1",
|
|
kbID: "kb-1",
|
|
docID: "doc-1",
|
|
taskID: "task-1",
|
|
docName: "test.pdf",
|
|
docType: "pdf",
|
|
}
|
|
for _, opt := range opts {
|
|
opt(cfg)
|
|
}
|
|
|
|
// Create Tenant
|
|
if err := db.Create(&entity.Tenant{
|
|
ID: cfg.tenantID,
|
|
LLMID: "gpt-4",
|
|
Status: StrPtr("1"),
|
|
}).Error; err != nil {
|
|
t.Fatalf("create tenant: %v", err)
|
|
}
|
|
|
|
// Create Knowledgebase
|
|
if err := db.Create(&entity.Knowledgebase{
|
|
ID: cfg.kbID,
|
|
TenantID: cfg.tenantID,
|
|
EmbdID: "embd-1",
|
|
Status: StrPtr("1"),
|
|
ParserConfig: entity.JSONMap{},
|
|
}).Error; err != nil {
|
|
t.Fatalf("create kb: %v", err)
|
|
}
|
|
|
|
// Create Document
|
|
doc := &entity.Document{
|
|
ID: cfg.docID,
|
|
KbID: cfg.kbID,
|
|
Name: &cfg.docName,
|
|
ParserID: "naive",
|
|
ParserConfig: entity.JSONMap{},
|
|
PipelineID: cfg.pipelineID,
|
|
Status: StrPtr("1"),
|
|
Type: cfg.docType,
|
|
}
|
|
loc := "doc_store/" + cfg.docID
|
|
doc.Location = &loc
|
|
if err := db.Create(doc).Error; err != nil {
|
|
t.Fatalf("create doc: %v", err)
|
|
}
|
|
|
|
// Create Task
|
|
if err := db.Create(&entity.Task{
|
|
ID: cfg.taskID,
|
|
DocID: cfg.docID,
|
|
TaskType: "dataflow",
|
|
FromPage: 0,
|
|
ToPage: 100000,
|
|
}).Error; err != nil {
|
|
t.Fatalf("create task: %v", err)
|
|
}
|
|
|
|
// Create IngestionTask
|
|
if err := db.Create(&entity.IngestionTask{
|
|
ID: cfg.taskID,
|
|
UserID: "u1",
|
|
DocumentID: cfg.docID,
|
|
DatasetID: cfg.kbID,
|
|
Status: common.RUNNING,
|
|
}).Error; err != nil {
|
|
t.Fatalf("create ingestion task: %v", err)
|
|
}
|
|
|
|
return cfg.tenantID, cfg.kbID, cfg.docID, cfg.taskID
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────
|
|
// Test Entity Helpers
|
|
// ──────────────────────────────────────────────────────────
|
|
|
|
// TestTask creates a test IngestionTask.
|
|
func TestTask(docID string) *entity.IngestionTask {
|
|
return &entity.IngestionTask{
|
|
ID: "task-1",
|
|
DocumentID: docID,
|
|
DatasetID: "kb-1",
|
|
}
|
|
}
|
|
|
|
// TestDoc creates a test Document.
|
|
func TestDoc(id string, docType string, suffix string, kbID ...string) *entity.Document {
|
|
name := "test." + suffix
|
|
loc := "doc_store/" + id
|
|
kb := "kb-1"
|
|
if len(kbID) > 0 {
|
|
kb = kbID[0]
|
|
}
|
|
return &entity.Document{
|
|
ID: id,
|
|
KbID: kb,
|
|
Type: docType,
|
|
Suffix: suffix,
|
|
Name: &name,
|
|
Location: &loc,
|
|
ParserID: "naive",
|
|
}
|
|
}
|