- Expand batch upload list area and optimize preview image layout - Improve upload speed tracking and display (server-side & client-side) - Reduce network detection log noise - Optimize Docker build process (caching, env validation) - Add shadow environment deployment support
252 lines
9.1 KiB
TypeScript
252 lines
9.1 KiB
TypeScript
/**
|
||
* R38修复:磁盘空间检查测试
|
||
*
|
||
* 测试内容:
|
||
* - formatBytes 函数
|
||
* - getDiskUsageLevel 函数(逻辑验证)
|
||
* - hasEnoughDiskSpace 函数(逻辑验证)
|
||
* - ensureEnoughDiskSpace 函数(逻辑验证)
|
||
*/
|
||
|
||
import { exec } from 'child_process'
|
||
import { promisify } from 'util'
|
||
import { formatBytes } from '../disk-space'
|
||
|
||
const execAsync = promisify(exec)
|
||
|
||
// Mock child_process.exec at module level
|
||
jest.mock('child_process', () => {
|
||
const originalModule = jest.requireActual('child_process')
|
||
return {
|
||
...originalModule,
|
||
exec: jest.fn(),
|
||
}
|
||
})
|
||
|
||
describe('R38: disk-space', () => {
|
||
beforeEach(() => {
|
||
jest.clearAllMocks()
|
||
})
|
||
|
||
describe('formatBytes', () => {
|
||
it('应该正确格式化字节数', () => {
|
||
expect(formatBytes(0)).toBe('0.00 B')
|
||
expect(formatBytes(1024)).toBe('1.00 KB')
|
||
expect(formatBytes(1024 * 1024)).toBe('1.00 MB')
|
||
expect(formatBytes(1024 * 1024 * 1024)).toBe('1.00 GB')
|
||
expect(formatBytes(1024 * 1024 * 1024 * 1024)).toBe('1.00 TB')
|
||
expect(formatBytes(1536)).toBe('1.50 KB')
|
||
})
|
||
})
|
||
|
||
describe('getDiskUsageLevel - 逻辑验证', () => {
|
||
it('使用率低于 70% 应该返回 ok', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(60% 使用率)
|
||
const stdout = JSON.stringify({ Used: 60000000000, Free: 40000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { getDiskUsageLevel } = require('../disk-space')
|
||
const result = await getDiskUsageLevel()
|
||
expect(result).toBe('ok')
|
||
})
|
||
|
||
it('使用率在 70%-90% 之间应该返回 warning', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(75% 使用率)
|
||
const stdout = JSON.stringify({ Used: 75000000000, Free: 25000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { getDiskUsageLevel } = require('../disk-space')
|
||
const result = await getDiskUsageLevel()
|
||
expect(result).toBe('warning')
|
||
})
|
||
|
||
it('使用率大于 90% 应该返回 critical', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(95% 使用率)
|
||
const stdout = JSON.stringify({ Used: 95000000000, Free: 5000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { getDiskUsageLevel } = require('../disk-space')
|
||
const result = await getDiskUsageLevel()
|
||
expect(result).toBe('critical')
|
||
})
|
||
|
||
it('无法检查时应该返回 ok', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟命令失败
|
||
;(callback as Function)(new Error('Command failed'), null)
|
||
return {} as any
|
||
})
|
||
|
||
const { getDiskUsageLevel } = require('../disk-space')
|
||
const result = await getDiskUsageLevel()
|
||
expect(result).toBe('ok')
|
||
})
|
||
})
|
||
|
||
describe('hasEnoughDiskSpace - 逻辑验证', () => {
|
||
it('当空间足够时应该返回 true', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(20% 使用率,80GB 可用)
|
||
const stdout = JSON.stringify({ Used: 20000000000, Free: 80000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { hasEnoughDiskSpace } = require('../disk-space')
|
||
const result = await hasEnoughDiskSpace(10 * 1024 * 1024 * 1024)
|
||
expect(result).toBe(true)
|
||
})
|
||
|
||
it('当可用空间不足时应该返回 false', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(90% 使用率,10GB 可用)
|
||
const stdout = JSON.stringify({ Used: 90000000000, Free: 10000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { hasEnoughDiskSpace } = require('../disk-space')
|
||
const result = await hasEnoughDiskSpace(20 * 1024 * 1024 * 1024)
|
||
expect(result).toBe(false)
|
||
})
|
||
|
||
it('当磁盘使用率过高时应该返回 false', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(95% 使用率,5GB 可用)
|
||
const stdout = JSON.stringify({ Used: 95000000000, Free: 5000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { hasEnoughDiskSpace } = require('../disk-space')
|
||
const result = await hasEnoughDiskSpace(100 * 1024 * 1024)
|
||
expect(result).toBe(false)
|
||
})
|
||
|
||
it('当无法检查时应该返回 true(保守处理)', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟命令失败
|
||
;(callback as Function)(new Error('Command failed'), null)
|
||
return {} as any
|
||
})
|
||
|
||
const { hasEnoughDiskSpace } = require('../disk-space')
|
||
const result = await hasEnoughDiskSpace(10 * 1024 * 1024 * 1024)
|
||
expect(result).toBe(true)
|
||
})
|
||
})
|
||
|
||
describe('ensureEnoughDiskSpace - 逻辑验证', () => {
|
||
it('当空间足够时不应该抛出错误', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(20% 使用率,80GB 可用)
|
||
const stdout = JSON.stringify({ Used: 20000000000, Free: 80000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { ensureEnoughDiskSpace } = require('../disk-space')
|
||
await expect(ensureEnoughDiskSpace(10 * 1024 * 1024 * 1024, '测试操作')).resolves.not.toThrow()
|
||
})
|
||
|
||
it('当空间不足时应该抛出错误', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟 PowerShell JSON 输出(90% 使用率,10GB 可用)
|
||
const stdout = JSON.stringify({ Used: 90000000000, Free: 10000000000 })
|
||
;(callback as Function)(null, { stdout, stderr: '' })
|
||
return {} as any
|
||
})
|
||
|
||
const { ensureEnoughDiskSpace } = require('../disk-space')
|
||
await expect(ensureEnoughDiskSpace(20 * 1024 * 1024 * 1024, '测试操作')).rejects.toThrow('磁盘空间不足')
|
||
})
|
||
|
||
it('当无法检查时不应该抛出错误', async () => {
|
||
const mockExec = exec as jest.MockedFunction<typeof exec>
|
||
mockExec.mockImplementationOnce((command, options, callback) => {
|
||
if (typeof options === 'function') {
|
||
callback = options
|
||
}
|
||
// 模拟命令失败
|
||
;(callback as Function)(new Error('Command failed'), null)
|
||
return {} as any
|
||
})
|
||
|
||
const { ensureEnoughDiskSpace } = require('../disk-space')
|
||
await expect(ensureEnoughDiskSpace(10 * 1024 * 1024 * 1024, '测试操作')).resolves.not.toThrow()
|
||
})
|
||
})
|
||
|
||
describe('数值计算验证', () => {
|
||
it('应该正确计算使用率百分比', () => {
|
||
const total = 100000000000
|
||
const used = 70000000000
|
||
const usePercent = (used / total) * 100
|
||
|
||
expect(usePercent).toBe(70)
|
||
})
|
||
|
||
it('应该正确计算保留空间', () => {
|
||
const total = 100000000000
|
||
const usePercent = 90
|
||
const minReserved = Math.max(total * 0.1, 5 * 1024 * 1024 * 1024)
|
||
|
||
expect(minReserved).toBeGreaterThanOrEqual(5 * 1024 * 1024 * 1024) // 至少 5GB
|
||
})
|
||
|
||
it('应该正确格式化字节大小', () => {
|
||
const bytes = 10 * 1024 * 1024 * 1024
|
||
expect(formatBytes(bytes)).toBe('10.00 GB')
|
||
})
|
||
})
|
||
})
|