mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-14 11:59:53 +03:00
167 lines
6.8 KiB
JavaScript
167 lines
6.8 KiB
JavaScript
import { beforeEach, describe, expect, it } from "vitest";
|
|
import MspHelper from "../../../src/js/msp/MSPHelper";
|
|
import MSPCodes from "../../../src/js/msp/MSPCodes";
|
|
import "../../../src/js/injected_methods";
|
|
import FC from "../../../src/js/fc";
|
|
import { API_VERSION_1_46 } from "../../../src/js/data_storage";
|
|
|
|
describe("MspHelper", () => {
|
|
const mspHelper = new MspHelper();
|
|
beforeEach(() => {
|
|
FC.resetState();
|
|
});
|
|
describe("process_data", () => {
|
|
it("refuses to process data with crc-error", () => {
|
|
let callbackCalled = false;
|
|
|
|
let callbackFunction = (item) => {
|
|
callbackCalled = true;
|
|
expect(item["crcError"]).toEqual(true);
|
|
expect(item["command"]).toEqual(MSPCodes.MSP_BOARD_INFO);
|
|
expect(item["length"]).toEqual(0);
|
|
};
|
|
|
|
mspHelper.process_data({
|
|
code: MSPCodes.MSP_BOARD_INFO,
|
|
dataView: new DataView(new Uint8Array([]).buffer),
|
|
crcError: true,
|
|
callbacks: [
|
|
{
|
|
callback: callbackFunction,
|
|
callbackOnError: true,
|
|
code: MSPCodes.MSP_BOARD_INFO,
|
|
},
|
|
],
|
|
});
|
|
|
|
expect(callbackCalled).toEqual(true);
|
|
});
|
|
it("handles MSP_API_VERSION correctly", () => {
|
|
let randomValues = crypto.getRandomValues(new Uint8Array(3));
|
|
const [mspProtocolVersion, apiVersionMajor, apiVersionMinor] = randomValues;
|
|
mspHelper.process_data({
|
|
code: MSPCodes.MSP_API_VERSION,
|
|
dataView: new DataView(randomValues.buffer),
|
|
crcError: false,
|
|
callbacks: [],
|
|
});
|
|
|
|
expect(FC.CONFIG.mspProtocolVersion).toEqual(mspProtocolVersion);
|
|
expect(FC.CONFIG.apiVersion).toEqual(`${apiVersionMajor}.${apiVersionMinor}.0`);
|
|
});
|
|
it("handles MSP_PIDNAMES correctly", () => {
|
|
let pidNamesCount = 1 + crypto.getRandomValues(new Uint8Array(1))[0];
|
|
let expectedNames = Array.from({ length: pidNamesCount }).map((_) => generateRandomString());
|
|
|
|
let lowLevelData = [];
|
|
appendStringToArray(lowLevelData, `${expectedNames.join(";")};`);
|
|
|
|
mspHelper.process_data({
|
|
code: MSPCodes.MSP_PIDNAMES,
|
|
dataView: new DataView(new Uint8Array(lowLevelData).buffer),
|
|
crcError: false,
|
|
callbacks: [],
|
|
});
|
|
|
|
expect(FC.PID_NAMES).toEqual(expectedNames);
|
|
});
|
|
it("handles MSP_MOTOR correctly", () => {
|
|
let motorCount = crypto.getRandomValues(new Uint8Array(1))[0] % 8;
|
|
let motorBytes = crypto.getRandomValues(new Uint16Array(motorCount));
|
|
|
|
mspHelper.process_data({
|
|
code: MSPCodes.MSP_MOTOR,
|
|
dataView: new DataView(new Uint16Array(motorBytes).buffer),
|
|
crcError: false,
|
|
callbacks: [],
|
|
});
|
|
expect(new Uint16Array(FC.MOTOR_DATA).slice(0, motorCount)).toEqual(motorBytes);
|
|
expect(FC.MOTOR_DATA.slice(motorCount, 8)).toContain(undefined);
|
|
});
|
|
it("handles MSP_BOARD_INFO correctly for API version", () => {
|
|
FC.CONFIG.apiVersion = API_VERSION_1_46;
|
|
let infoBuffer = [];
|
|
|
|
const boardIdentifier = appendStringToArray(infoBuffer, generateRandomString(4)); // set board-identifier
|
|
|
|
infoBuffer.push16(0xdead); // set board version
|
|
infoBuffer.push8(0x12); // set board type
|
|
infoBuffer.push8(0x32); // set target capabilities
|
|
|
|
const targetName = appendStringToArray(infoBuffer, generateRandomString(), true); // set target name
|
|
const boardName = appendStringToArray(infoBuffer, generateRandomString(), true); // set board name
|
|
const manufacturerId = appendStringToArray(infoBuffer, generateRandomString(), true); // set board name
|
|
const signature = crypto.getRandomValues(new Uint8Array(32));
|
|
|
|
signature.forEach((element) => infoBuffer.push8(element));
|
|
infoBuffer.push8(0xfa); // mcu type id
|
|
infoBuffer.push8(0xbb); // configuration state
|
|
infoBuffer.push16(0xbaab); // sample rate
|
|
infoBuffer.push32(0xdeadbeef); // configuration problems
|
|
|
|
mspHelper.process_data({
|
|
code: MSPCodes.MSP_BOARD_INFO,
|
|
dataView: new DataView(new Uint8Array(infoBuffer).buffer),
|
|
crcError: false,
|
|
callbacks: [],
|
|
});
|
|
|
|
expect(FC.CONFIG.boardIdentifier).toEqual(boardIdentifier);
|
|
expect(FC.CONFIG.boardVersion).toEqual(0xdead);
|
|
expect(FC.CONFIG.boardType).toEqual(0x12);
|
|
expect(FC.CONFIG.targetCapabilities).toEqual(0x32);
|
|
expect(FC.CONFIG.targetName).toEqual(targetName);
|
|
expect(FC.CONFIG.boardName).toEqual(boardName);
|
|
expect(FC.CONFIG.manufacturerId).toEqual(manufacturerId);
|
|
expect(new Uint8Array(FC.CONFIG.signature)).toEqual(signature);
|
|
expect(FC.CONFIG.mcuTypeId).toEqual(0xfa);
|
|
|
|
expect(FC.CONFIG.configurationState).toEqual(0xbb);
|
|
expect(FC.CONFIG.sampleRateHz).toEqual(0xbaab);
|
|
expect(FC.CONFIG.configurationProblems).toEqual(0xdeadbeef);
|
|
});
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Appends given string to an array. If required, it will append length of the string by length.
|
|
* @param destination array to which we append given string (and length if required)
|
|
* @param source string to append to an array
|
|
* @param prefixWithLength should we prefix the string by its length in the array
|
|
* @returns {*} string that was requested to be inserted to the array
|
|
*/
|
|
function appendStringToArray(destination, source, prefixWithLength = false) {
|
|
const size = source.length;
|
|
|
|
if (prefixWithLength) {
|
|
destination.push8(source.length);
|
|
}
|
|
|
|
for (let i = 0; i < size; i++) {
|
|
destination.push8(source.charCodeAt(i));
|
|
}
|
|
|
|
return source;
|
|
}
|
|
|
|
/**
|
|
* Generates a random string of required length. If required length is -1, it will generate a random string of a random length.
|
|
* @param length required random string length. If lower than 0, it will generate a string of random length.
|
|
* @returns {string} random string (composed of letters [A-Za-z0-9])
|
|
*/
|
|
function generateRandomString(length = -1) {
|
|
let result = "";
|
|
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
const charactersLength = characters.length;
|
|
|
|
if (length < 0) {
|
|
length = crypto.getRandomValues(new Uint8Array(1))[0];
|
|
}
|
|
|
|
const signature = crypto.getRandomValues(new Uint8Array(length));
|
|
for (let i = 0; i < length; i++) {
|
|
result += characters.charAt(signature[i] % charactersLength);
|
|
}
|
|
|
|
return result;
|
|
}
|