UNPKG

chrome-devtools-frontend

Version:
202 lines (172 loc) • 8.41 kB
// Copyright (c) 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as SDK from '../../core/sdk/sdk.js'; import {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js'; import * as LinearMemoryInspectorComponents from './components/components.js'; import * as LinearMemoryInspector from './linear_memory_inspector.js'; const {LinearMemoryInspectorController} = LinearMemoryInspector; const {ValueInterpreterDisplayUtils} = LinearMemoryInspectorComponents; class MockRemoteObject extends SDK.RemoteObject.LocalJSONObject { override arrayBufferByteLength() { return this.value.byteLength; } override get subtype(): string|undefined { return 'arraybuffer'; } } function createWrapper(array: Uint8Array<ArrayBuffer>) { const mockRemoteObj = new MockRemoteObject(array.buffer); const mockRemoteArrayBuffer = new SDK.RemoteObject.RemoteArrayBuffer(mockRemoteObj); return new LinearMemoryInspectorController.RemoteArrayBufferWrapper(mockRemoteArrayBuffer); } describeWithEnvironment('LinearMemoryInspectorController', () => { it('throws an error on an invalid (out-of-bounds) memory range request', async () => { const array = new Uint8Array([2, 4, 6, 2, 4]); const wrapper = createWrapper(array); try { await LinearMemoryInspectorController.LinearMemoryInspectorController.getMemoryRange(wrapper, 10, 20); throw new Error('Function did now throw.'); } catch (e) { const error = e as Error; assert.strictEqual(error.message, 'Requested range is out of bounds.'); } }); it('throws an error on an invalid memory range request', async () => { const array = new Uint8Array([2, 4, 6, 2, 4]); const wrapper = createWrapper(array); try { await LinearMemoryInspectorController.LinearMemoryInspectorController.getMemoryRange(wrapper, 20, 10); throw new Error('Function did now throw.'); } catch (e) { const error = e as Error; assert.strictEqual(error.message, 'Requested range is out of bounds.'); } }); it('can pull updated data on memory range request', async () => { const array = new Uint8Array([2, 4, 6, 2, 4]); const wrapper = createWrapper(array); const valuesBefore = await LinearMemoryInspectorController.LinearMemoryInspectorController.getMemoryRange(wrapper, 0, array.length); assert.strictEqual(valuesBefore.length, array.length); for (let i = 0; i < array.length; ++i) { assert.strictEqual(valuesBefore[i], array[i]); } const changedIndex = 0; const changedValue = 10; array[changedIndex] = changedValue; const valuesAfter = await LinearMemoryInspectorController.LinearMemoryInspectorController.getMemoryRange(wrapper, 0, array.length); assert.strictEqual(valuesAfter.length, valuesBefore.length); for (let i = 0; i < valuesBefore.length; ++i) { if (i === changedIndex) { assert.strictEqual(valuesAfter[i], changedValue); } else { assert.strictEqual(valuesAfter[i], valuesBefore[i]); } } }); it('triggers saving and loading of settings on settings changed event', () => { const instance = LinearMemoryInspectorController.LinearMemoryInspectorController.instance(); const valueTypes = new Set([ValueInterpreterDisplayUtils.ValueType.INT16, ValueInterpreterDisplayUtils.ValueType.FLOAT32]); const valueTypeModes = new Map( [[ValueInterpreterDisplayUtils.ValueType.INT16, ValueInterpreterDisplayUtils.ValueTypeMode.HEXADECIMAL]]); const settings = { valueTypes, modes: valueTypeModes, endianness: ValueInterpreterDisplayUtils.Endianness.LITTLE, }; const defaultSettings = instance.loadSettings(); instance.saveSettings(settings); assert.notDeepEqual(defaultSettings, settings); const actualSettings = instance.loadSettings(); assert.deepEqual(actualSettings, settings); }); it('returns undefined when error happens in evaluateExpression', async () => { const errorText = 'This is a test error'; const callFrame = { evaluate: ({}) => { return new Promise(resolve => { resolve({error: errorText} as SDK.RuntimeModel.EvaluationResult); }); }, } as SDK.DebuggerModel.CallFrame; const stub = sinon.stub(console, 'error'); const instance = LinearMemoryInspectorController.LinearMemoryInspectorController.instance(); const expressionName = 'myCar'; const result = await instance.evaluateExpression(callFrame, expressionName); assert.isUndefined(result); sinon.assert.calledOnceWithExactly( stub, `Tried to evaluate the expression '${expressionName}' but got an error: ${errorText}`); }); it('returns undefined when exceptionDetails is set on the result of evaluateExpression', async () => { const exceptionText = 'This is a test exception\'s detail text'; const callFrame = { evaluate: ({}) => { return new Promise(resolve => { resolve({ object: {type: 'object'} as SDK.RemoteObject.RemoteObject, exceptionDetails: {text: exceptionText}, } as SDK.RuntimeModel.EvaluationResult); }); }, } as SDK.DebuggerModel.CallFrame; const stub = sinon.stub(console, 'error'); const instance = LinearMemoryInspectorController.LinearMemoryInspectorController.instance(); const expressionName = 'myCar.manufacturer'; const result = await instance.evaluateExpression(callFrame, expressionName); assert.isUndefined(result); sinon.assert.calledOnceWithExactly( stub, `Tried to evaluate the expression '${expressionName}' but got an exception: ${exceptionText}`); }); it('returns RemoteObject when no exception happens in evaluateExpression', async () => { const expectedObj = {type: 'object'} as SDK.RemoteObject.RemoteObject; const callFrame = { evaluate: ({}) => { return new Promise(resolve => { resolve({ object: expectedObj, } as SDK.RuntimeModel.EvaluationResult); }); }, } as SDK.DebuggerModel.CallFrame; const instance = LinearMemoryInspectorController.LinearMemoryInspectorController.instance(); const result = await instance.evaluateExpression(callFrame, 'myCar.manufacturer'); assert.deepEqual(result, expectedObj); }); it('removes the provided highlightInfo when it is stored in the Controller', () => { const highlightInfo = {startAddress: 0, size: 16, name: 'myNumbers', type: 'int[]'} as LinearMemoryInspectorComponents.LinearMemoryViewerUtils.HighlightInfo; const bufferId = 'someBufferId'; const instance = LinearMemoryInspectorController.LinearMemoryInspectorController.instance(); instance.setHighlightInfo(bufferId, highlightInfo); assert.deepEqual(instance.getHighlightInfo(bufferId), highlightInfo); instance.removeHighlight(bufferId, highlightInfo); assert.isUndefined(instance.getHighlightInfo(bufferId)); }); it('does not change the stored highlight when the provided highlightInfo does not match', () => { const highlightInfo = {startAddress: 0, size: 16, name: 'myNumbers', type: 'int[]'} as LinearMemoryInspectorComponents.LinearMemoryViewerUtils.HighlightInfo; const differentHighlightInfo = {startAddress: 20, size: 50, name: 'myBytes', type: 'bool[]'} as LinearMemoryInspectorComponents.LinearMemoryViewerUtils.HighlightInfo; const bufferId = 'someBufferId'; const instance = LinearMemoryInspectorController.LinearMemoryInspectorController.instance(); instance.setHighlightInfo(bufferId, highlightInfo); assert.deepEqual(instance.getHighlightInfo(bufferId), highlightInfo); instance.removeHighlight(bufferId, differentHighlightInfo); assert.deepEqual(instance.getHighlightInfo(bufferId), highlightInfo); }); }); describe('RemoteArrayBufferWrapper', () => { it('correctly wraps the remote object', async () => { const array = new Uint8Array([2, 4, 6, 2, 4]); const wrapper = createWrapper(array); assert.strictEqual(wrapper.length(), array.length); const extractedArray = await wrapper.getRange(0, 3); assert.lengthOf(extractedArray, 3); for (let i = 0; i < 3; ++i) { assert.deepEqual(array[i], extractedArray[i]); } }); });