Files
pioarduino-vscode-debug/__tests__/frontend/memory-write.test.ts
T
2026-05-01 22:03:05 +02:00

274 lines
8.7 KiB
TypeScript

/**
* Tests for memory write operations.
*/
import { MemoryContentProvider } from '../../src/frontend/memory_content_provider'
// Mock vscode with controllable debug session
const mockCustomRequest = jest.fn()
let hasActiveDebugSession = false
jest.mock('vscode', () => ({
window: {
createTextEditorDecorationType: jest.fn().mockReturnValue({
dispose: jest.fn()
}),
showErrorMessage: jest.fn().mockResolvedValue(undefined),
showInformationMessage: jest.fn().mockResolvedValue(undefined)
},
debug: {
get activeDebugSession() {
return hasActiveDebugSession ? {
customRequest: mockCustomRequest
} : undefined
}
},
EventEmitter: jest.fn().mockImplementation(() => ({
event: jest.fn(),
fire: jest.fn()
})),
Position: jest.fn().mockImplementation((line: number, character: number) => ({
line,
character
})),
Range: jest.fn(),
OverviewRulerLane: {
Right: 4
},
Uri: {
parse: jest.fn()
},
workspace: {
textDocuments: []
}
}))
describe('Memory Write Operations', () => {
let provider: MemoryContentProvider
beforeEach(() => {
provider = new MemoryContentProvider()
hasActiveDebugSession = true
mockCustomRequest.mockClear()
})
afterEach(() => {
hasActiveDebugSession = false
})
describe('writeByte', () => {
test('should write single byte successfully', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const success = await provider.writeByte(0x20000000, 0xAB)
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: 'ab'
})
})
test('should write byte 0x00', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const success = await provider.writeByte(0x20000000, 0x00)
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: '00'
})
})
test('should write byte 0xFF', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const success = await provider.writeByte(0x20000000, 0xFF)
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: 'ff'
})
})
test('should reject value > 0xFF with an error', async () => {
const success = await provider.writeByte(0x20000000, 0x1AB)
expect(success).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
})
test('should reject negative values', async () => {
const success = await provider.writeByte(0x20000000, -1)
expect(success).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
})
test('should reject fractional values', async () => {
const successA = await provider.writeByte(0x20000000, 1.5)
expect(successA).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
const successB = await provider.writeByte(0x20000000, 0.5)
expect(successB).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
})
test('should return false when no debug session', async () => {
hasActiveDebugSession = false
const success = await provider.writeByte(0x20000000, 0xAB)
expect(success).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
})
test('should return false on write error', async () => {
mockCustomRequest.mockRejectedValue(new Error('Memory access denied'))
const success = await provider.writeByte(0x20000000, 0xAB)
expect(success).toBe(false)
})
test('should write to different addresses', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
// Test various addresses
const addresses = [
0x00000000,
0x20000000,
0x40000000,
0x08000000,
0xFFFFFFFF
]
for (const address of addresses) {
mockCustomRequest.mockClear()
const success = await provider.writeByte(address, 0x42)
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address,
data: '42'
})
}
})
})
describe('writeBytes', () => {
test('should write multiple bytes successfully', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const success = await provider.writeBytes(0x20000000, [0x12, 0x34, 0x56, 0x78])
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: '12345678'
})
})
test('should write single byte array', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const success = await provider.writeBytes(0x20000000, [0xAB])
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: 'ab'
})
})
test('should write empty array', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const success = await provider.writeBytes(0x20000000, [])
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: ''
})
})
test('should reject array containing values > 0xFF with an error', async () => {
const success = await provider.writeBytes(0x20000000, [0x1FF, 0x2AB, 0x3CD])
expect(success).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
})
test('should return false when no debug session', async () => {
hasActiveDebugSession = false
const success = await provider.writeBytes(0x20000000, [0x12, 0x34])
expect(success).toBe(false)
expect(mockCustomRequest).not.toHaveBeenCalled()
})
test('should return false on write error', async () => {
mockCustomRequest.mockRejectedValue(new Error('Target not halted'))
const success = await provider.writeBytes(0x20000000, [0x12, 0x34])
expect(success).toBe(false)
})
test('should write large byte arrays', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
const largeArray = new Array(256).fill(0).map((_, i) => i)
const success = await provider.writeBytes(0x20000000, largeArray)
expect(success).toBe(true)
expect(mockCustomRequest).toHaveBeenCalledWith('write-memory', {
address: 0x20000000,
data: largeArray.map(v => v.toString(16).padStart(2, '0')).join('')
})
})
})
describe('Hex Formatting', () => {
test('should format bytes as lowercase hex', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
await provider.writeByte(0x20000000, 0xAB)
const callArgs = mockCustomRequest.mock.calls[0]
expect(callArgs[1].data).toBe('ab')
})
test('should pad single hex digit with zero', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
await provider.writeByte(0x20000000, 0x5)
const callArgs = mockCustomRequest.mock.calls[0]
expect(callArgs[1].data).toBe('05')
})
test('should handle 0x00 correctly', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
await provider.writeByte(0x20000000, 0x00)
const callArgs = mockCustomRequest.mock.calls[0]
expect(callArgs[1].data).toBe('00')
})
test('should handle 0xFF correctly', async () => {
mockCustomRequest.mockResolvedValue({ success: true })
await provider.writeByte(0x20000000, 0xFF)
const callArgs = mockCustomRequest.mock.calls[0]
expect(callArgs[1].data).toBe('ff')
})
})
})