52 lines
1.8 KiB
TypeScript
52 lines
1.8 KiB
TypeScript
// tests/main/db-open-atomic-redteam-r2-1.test.ts
|
|
// 계정 DB 가 손상돼 열리지 않아도 앱이 DB 없이 남지 않는다 — openForUser 는 새 DB 를 연 뒤에야
|
|
// 이전 DB 를 닫는다(원자적 교체).
|
|
|
|
import { afterEach, describe, expect, it } from 'vitest'
|
|
import fs from 'fs'
|
|
import path from 'path'
|
|
import { app } from 'electron'
|
|
import { ErrorCode } from '@d3ro/core/errors'
|
|
import { sql } from 'drizzle-orm'
|
|
import {
|
|
closeCurrent,
|
|
getCurrentUserId,
|
|
getDatabase,
|
|
isDatabaseOpen,
|
|
openForUser,
|
|
openLocal,
|
|
} from '../../src/main/db'
|
|
|
|
const CORRUPT_USER = `corrupt-${process.pid}-${Date.now()}`
|
|
const GOOD_USER = `good-${process.pid}-${Date.now()}`
|
|
|
|
function userDir(userId: string): string {
|
|
return path.join(app.getPath('userData'), 'users', userId)
|
|
}
|
|
|
|
afterEach(() => {
|
|
closeCurrent()
|
|
for (const id of [CORRUPT_USER, GOOD_USER]) fs.rmSync(userDir(id), { recursive: true, force: true })
|
|
})
|
|
|
|
describe('openForUser 원자적 교체', () => {
|
|
it('손상된 계정 DB 를 열지 못하면 이전(로컬) DB 가 그대로 열려 있다', () => {
|
|
openLocal()
|
|
fs.mkdirSync(userDir(CORRUPT_USER), { recursive: true })
|
|
fs.writeFileSync(path.join(userDir(CORRUPT_USER), 'd3ro.db'), 'this is not a sqlite database'.repeat(64))
|
|
|
|
expect(() => openForUser(CORRUPT_USER)).toThrow(expect.objectContaining({ code: ErrorCode.DBOpenFailed }))
|
|
|
|
expect(isDatabaseOpen()).toBe(true)
|
|
expect(getCurrentUserId()).toBe('_local')
|
|
expect(() => getDatabase().run(sql`SELECT 1`)).not.toThrow()
|
|
})
|
|
|
|
it('정상 계정 DB 는 열고 이전 DB 와 교체한다', () => {
|
|
openLocal()
|
|
const result = openForUser(GOOD_USER)
|
|
expect(result.dbPath).toContain(GOOD_USER)
|
|
expect(getCurrentUserId()).toBe(GOOD_USER)
|
|
expect(() => getDatabase().run(sql`SELECT 1`)).not.toThrow()
|
|
})
|
|
})
|