Skip to main content
Glama
YUChoe

SQLite MCP Server

by YUChoe
insertData.test.ts8.96 kB
/** * 데이터 삽입 도구 테스트 * **Feature: sqlite-mcp-server, Property 4: 데이터 삽입 라운드트립** */ import * as fc from 'fast-check'; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; import { createTableTool } from './createTable'; import { insertDataTool } from './insertData'; import { DatabaseManager } from '../database/DatabaseManager'; import type { CreateTableInput, InsertDataInput } from '../types/schemas'; describe('Insert Data Tool', () => { let tempDir: string; let dbManager: DatabaseManager; beforeEach(() => { // 임시 디렉토리 생성 tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'sqlite-test-')); dbManager = new DatabaseManager(); }); afterEach(() => { // 정리 dbManager.closeAllDatabases(); if (fs.existsSync(tempDir)) { fs.rmSync(tempDir, { recursive: true, force: true }); } }); test('**Feature: sqlite-mcp-server, Property 4: 데이터 삽입 라운드트립**', async () => { await fc.assert( fc.asyncProperty( // 테이블 이름 생성기 fc.constantFrom('table1', 'table2', 'table3', 'users', 'items', 'data', 'records', 'entries'), // 테이블 스키마 생성기 fc.array( fc.record({ name: fc.constantFrom('col1', 'col2', 'col3', 'col4', 'col5', 'id', 'name', 'value', 'data', 'info'), type: fc.constantFrom('INTEGER', 'TEXT', 'REAL') }), { minLength: 1, maxLength: 3 } ), // 삽입할 데이터 생성기 fc.record({ textValue: fc.string({ maxLength: 100 }), intValue: fc.integer({ min: -1000000, max: 1000000 }), realValue: fc.float({ min: -1000.0, max: 1000.0 }), boolValue: fc.boolean(), nullValue: fc.constant(null) }), async (tableName, schemaColumns, testData) => { const dbPath = path.join(tempDir, `test_${Date.now()}_${Math.random()}.db`); // 중복 컬럼명 제거 const uniqueColumns = schemaColumns.filter((col, index, arr) => arr.findIndex(c => c.name === col.name) === index ); if (uniqueColumns.length === 0) return; try { // 테이블 생성 const createInput: CreateTableInput = { dbPath, tableName, columns: uniqueColumns }; const createResult = await createTableTool.handler(createInput); expect(createResult.structuredContent?.success).toBe(true); // 삽입할 데이터 준비 (스키마에 맞게) const insertData: Record<string, any> = {}; for (const column of uniqueColumns) { switch (column.type) { case 'INTEGER': insertData[column.name] = testData.intValue; break; case 'TEXT': insertData[column.name] = testData.textValue; break; case 'REAL': insertData[column.name] = testData.realValue; break; } } // 데이터 삽입 const insertInput: InsertDataInput = { dbPath, tableName, data: insertData }; const insertResult = await insertDataTool.handler(insertInput); expect(insertResult.structuredContent?.success).toBe(true); expect(insertResult.structuredContent?.lastInsertRowid).toBeDefined(); const insertedId = insertResult.structuredContent?.lastInsertRowid; // 데이터 조회하여 라운드트립 검증 const selectResult = dbManager.executeQuery( dbPath, `SELECT * FROM ${tableName} WHERE rowid = ?`, [insertedId] ); expect(selectResult.success).toBe(true); expect(selectResult.data).toHaveLength(1); const retrievedData = selectResult.data?.[0]; expect(retrievedData).toBeDefined(); // 각 컬럼 값이 올바르게 저장되고 조회되는지 확인 for (const column of uniqueColumns) { const originalValue = insertData[column.name]; const retrievedValue = retrievedData[column.name]; switch (column.type) { case 'INTEGER': expect(retrievedValue).toBe(originalValue); break; case 'TEXT': expect(retrievedValue).toBe(originalValue); break; case 'REAL': // 부동소수점 비교는 근사치로 if (originalValue !== null) { expect(Math.abs(retrievedValue - originalValue)).toBeLessThan(0.0001); } else { expect(retrievedValue).toBeNull(); } break; } } } finally { // 데이터베이스 연결 명시적으로 닫기 dbManager.closeDatabase(dbPath); } } ), { numRuns: 100 } ); }); test('should handle empty data object', async () => { const dbPath = path.join(tempDir, 'test.db'); try { // 먼저 테이블 생성 const createInput: CreateTableInput = { dbPath, tableName: 'test_table', columns: [{ name: 'id', type: 'INTEGER' }] }; await createTableTool.handler(createInput); // 빈 데이터로 삽입 시도 const insertInput: InsertDataInput = { dbPath, tableName: 'test_table', data: {} }; const result = await insertDataTool.handler(insertInput); expect(result.structuredContent?.success).toBe(false); expect(result.structuredContent?.error).toContain('삽입할 데이터가 필요합니다'); } finally { dbManager.closeDatabase(dbPath); } }); test('should handle invalid table name', async () => { const dbPath = path.join(tempDir, 'test.db'); try { const insertInput: InsertDataInput = { dbPath, tableName: '123invalid', data: { id: 1 } }; const result = await insertDataTool.handler(insertInput); expect(result.structuredContent?.success).toBe(false); expect(result.structuredContent?.error).toContain('유효한 테이블 이름이어야 합니다'); } finally { dbManager.closeDatabase(dbPath); } }); test('should handle invalid column names', async () => { const dbPath = path.join(tempDir, 'test.db'); try { const insertInput: InsertDataInput = { dbPath, tableName: 'test_table', data: { '123invalid': 'value' } }; const result = await insertDataTool.handler(insertInput); expect(result.structuredContent?.success).toBe(false); expect(result.structuredContent?.error).toContain('유효하지 않은 컬럼 이름'); } finally { dbManager.closeDatabase(dbPath); } }); test('should handle various data types', async () => { const dbPath = path.join(tempDir, 'test.db'); try { // 다양한 타입의 컬럼을 가진 테이블 생성 const createInput: CreateTableInput = { dbPath, tableName: 'test_table', columns: [ { name: 'text_col', type: 'TEXT' }, { name: 'int_col', type: 'INTEGER' }, { name: 'real_col', type: 'REAL' }, { name: 'bool_col', type: 'INTEGER' }, { name: 'null_col', type: 'TEXT' } ] }; await createTableTool.handler(createInput); // 다양한 타입의 데이터 삽입 const insertInput: InsertDataInput = { dbPath, tableName: 'test_table', data: { text_col: 'test string', int_col: 42, real_col: 3.14, bool_col: true, null_col: null } }; const result = await insertDataTool.handler(insertInput); expect(result.structuredContent?.success).toBe(true); // 데이터 조회하여 확인 const selectResult = dbManager.executeQuery( dbPath, 'SELECT * FROM test_table' ); expect(selectResult.success).toBe(true); expect(selectResult.data).toHaveLength(1); const row = selectResult.data?.[0]; expect(row.text_col).toBe('test string'); expect(row.int_col).toBe(42); expect(Math.abs(row.real_col - 3.14)).toBeLessThan(0.0001); expect(row.bool_col).toBe(1); // boolean은 1로 저장됨 expect(row.null_col).toBeNull(); } finally { dbManager.closeDatabase(dbPath); } }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/YUChoe/sqlite-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server