test(adb): add tests for base64 module

This commit is contained in:
Simon Chan 2020-12-14 13:10:43 +08:00
parent e5f6b34ed0
commit 8b648991e8
9 changed files with 5019 additions and 32 deletions

View file

@ -28,6 +28,6 @@ jobs:
env:
CI: true
- run: npm run build --if-present
# - run: npm test
# env:
# CI: true
- run: npm test
env:
CI: true

View file

@ -6,7 +6,8 @@
"build": "lerna run --scope @yume-chan/adb-backend-web build",
"build:watch": "lerna run --scope @yume-chan/adb-backend-web --stream build:watch",
"build:demo": "lerna run --scope demo --stream build",
"start:demo": "lerna run --scope demo --stream start"
"start:demo": "lerna run --scope demo --stream start",
"test": "lerna run --stream test"
},
"devDependencies": {
"lerna": "3.22.1"

4
packages/adb/.npmignore Normal file
View file

@ -0,0 +1,4 @@
__snapshots__
**/*.spec.*
jest.config.js
tsconfig.tsbuildinfo

View file

@ -0,0 +1,5 @@
module.exports = {
preset: 'ts-jest',
testRegex: 'src/.*/*.spec.tsx?$',
testEnvironment: 'node',
};

File diff suppressed because it is too large Load diff

View file

@ -15,12 +15,16 @@
},
"scripts": {
"build": "tsc -b",
"build:watch": "tsc -b -w"
"build:watch": "tsc -b -w",
"test": "jest"
},
"bugs": {
"url": "https://github.com/yume-chan/ya-webadb/issues"
},
"devDependencies": {
"@types/jest": "26.0.19",
"jest": "26.6.3",
"ts-jest": "26.4.4",
"typescript": "4.1.2"
},
"dependencies": {

View file

@ -71,7 +71,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
}
const publicKeyLength = calculatePublicKeyLength();
const publicKeyBase64Length = calculateBase64EncodedLength(publicKeyLength);
const [publicKeyBase64Length] = calculateBase64EncodedLength(publicKeyLength);
// The public key is null terminated,
// So we allocate the buffer with one extra byte.

View file

@ -0,0 +1,170 @@
import { calculateBase64EncodedLength, decodeBase64, encodeBase64 } from './base64';
describe('base64', () => {
describe('calculateBase64EncodedLength', () => {
it('input 0', () => {
expect(calculateBase64EncodedLength(0)).toEqual([0, 0]);
});
it('input 1', () => {
expect(calculateBase64EncodedLength(1)).toEqual([4, 2]);
});
it('input 2', () => {
expect(calculateBase64EncodedLength(2)).toEqual([4, 1]);
});
it('input 3', () => {
expect(calculateBase64EncodedLength(3)).toEqual([4, 0]);
});
it('input 4', () => {
expect(calculateBase64EncodedLength(4)).toEqual([8, 2]);
});
it('input 5', () => {
expect(calculateBase64EncodedLength(5)).toEqual([8, 1]);
});
it('input 6', () => {
expect(calculateBase64EncodedLength(6)).toEqual([8, 0]);
});
});
describe('decodeBase64', () => {
it("input length 0", () => {
expect(new Uint8Array(decodeBase64(''))).toEqual(new Uint8Array());
});
it("input length 1", () => {
expect(new Uint8Array(decodeBase64('AA=='))).toEqual(new Uint8Array([0]));
});
it("input length 2", () => {
expect(new Uint8Array(decodeBase64('AAE='))).toEqual(new Uint8Array([0, 1]));
});
it("input length 3", () => {
expect(new Uint8Array(decodeBase64('AAEC'))).toEqual(new Uint8Array([0, 1, 2]));
});
it("input length 4", () => {
expect(new Uint8Array(decodeBase64('AAECAw=='))).toEqual(new Uint8Array([0, 1, 2, 3]));
});
it("input length 5", () => {
expect(new Uint8Array(decodeBase64('AAECAwQ='))).toEqual(new Uint8Array([0, 1, 2, 3, 4]));
});
it("input length 6", () => {
expect(new Uint8Array(decodeBase64('AAECAwQF'))).toEqual(new Uint8Array([0, 1, 2, 3, 4, 5]));
});
it("all byte values", () => {
expect(
new Uint8Array(
decodeBase64(
'AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w=='
)
)
).toEqual(new Uint8Array(Array.from({ length: 256 }, (_, index) => index)));
});
});
describe('encodeBase64', () => {
it('input length 0', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array()
)
)
).toEqual(new Uint8Array());
});
it('input length 1', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
[0]
)
)
)
).toEqual(new Uint8Array([65, 65, 61, 61])); // AA==
});
it('input length 2', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
[0, 1]
)
)
)
).toEqual(new Uint8Array([65, 65, 69, 61])); // AAE=
});
it('input length 3', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
[0, 1, 2]
)
)
)
).toEqual(new Uint8Array([65, 65, 69, 67])); // AAEC
});
it('input length 4', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
[0, 1, 2, 3]
)
)
)
).toEqual(new Uint8Array([65, 65, 69, 67, 65, 119, 61, 61])); // AAECAw==
});
it('input length 5', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
[0, 1, 2, 3, 4]
)
)
)
).toEqual(new Uint8Array([65, 65, 69, 67, 65, 119, 81, 61])); // AAECAwQ=
});
it('input length 6', () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
[0, 1, 2, 3, 4, 5]
)
)
)
).toEqual(new Uint8Array([65, 65, 69, 67, 65, 119, 81, 70])); // AAECAwQF
});
it("all byte values", () => {
expect(
new Uint8Array(
encodeBase64(
new Uint8Array(
Array.from({ length: 256 }, (_, index) => index)
)
)
)
).toEqual(new Uint8Array([65, 65, 69, 67, 65, 119, 81, 70, 66, 103, 99, 73, 67, 81, 111, 76, 68, 65, 48, 79, 68, 120, 65, 82, 69, 104, 77, 85, 70, 82, 89, 88, 71, 66, 107, 97, 71, 120, 119, 100, 72, 104, 56, 103, 73, 83, 73, 106, 74, 67, 85, 109, 74, 121, 103, 112, 75, 105, 115, 115, 76, 83, 52, 118, 77, 68, 69, 121, 77, 122, 81, 49, 78, 106, 99, 52, 79, 84, 111, 55, 80, 68, 48, 43, 80, 48, 66, 66, 81, 107, 78, 69, 82, 85, 90, 72, 83, 69, 108, 75, 83, 48, 120, 78, 84, 107, 57, 81, 85, 86, 74, 84, 86, 70, 86, 87, 86, 49, 104, 90, 87, 108, 116, 99, 88, 86, 53, 102, 89, 71, 70, 105, 89, 50, 82, 108, 90, 109, 100, 111, 97, 87, 112, 114, 98, 71, 49, 117, 98, 51, 66, 120, 99, 110, 78, 48, 100, 88, 90, 51, 101, 72, 108, 54, 101, 51, 120, 57, 102, 110, 43, 65, 103, 89, 75, 68, 104, 73, 87, 71, 104, 52, 105, 74, 105, 111, 117, 77, 106, 89, 54, 80, 107, 74, 71, 83, 107, 53, 83, 86, 108, 112, 101, 89, 109, 90, 113, 98, 110, 74, 50, 101, 110, 54, 67, 104, 111, 113, 79, 107, 112, 97, 97, 110, 113, 75, 109, 113, 113, 54, 121, 116, 114, 113, 43, 119, 115, 98, 75, 122, 116, 76, 87, 50, 116, 55, 105, 53, 117, 114, 117, 56, 118, 98, 54, 47, 119, 77, 72, 67, 119, 56, 84, 70, 120, 115, 102, 73, 121, 99, 114, 76, 122, 77, 51, 79, 122, 57, 68, 82, 48, 116, 80, 85, 49, 100, 98, 88, 50, 78, 110, 97, 50, 57, 122, 100, 51, 116, 47, 103, 52, 101, 76, 106, 53, 79, 88, 109, 53, 43, 106, 112, 54, 117, 118, 115, 55, 101, 55, 118, 56, 80, 72, 121, 56, 47, 84, 49, 57, 118, 102, 52, 43, 102, 114, 55, 47, 80, 51, 43, 47, 119, 61, 61]));
// AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4vMDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v8PHy8/T19vf4+fr7/P3+/w==
});
});
});

View file

@ -1,7 +1,7 @@
// Prepare maps for O(1) searching
const charToIndex: Record<string, number> = {};
const indexToChar: number[] = [];
const padding = '='.charCodeAt(0);
const paddingChar = '='.charCodeAt(0);
function addRange(start: string, end: string) {
const charCodeStart = start.charCodeAt(0);
@ -20,40 +20,42 @@ addRange('0', '9');
addRange('+', '+');
addRange('/', '/');
export function calculateBase64EncodedLength(inputLength: number): number {
return Math.ceil(inputLength / 3) * 4;
export function calculateBase64EncodedLength(inputLength: number): [outputLength: number, paddingLength: number] {
const remainder = inputLength % 3;
const paddingLength = remainder !== 0 ? 3 - remainder : 0;
return [(inputLength + paddingLength) / 3 * 4, paddingLength];
}
export function encodeBase64(
input: ArrayBuffer | Uint8Array,
inputOffset?: number,
inputLength?: number,
): ArrayBuffer;
): ArrayBuffer; // overload 1
export function encodeBase64(
input: ArrayBuffer | Uint8Array,
output: ArrayBuffer | Uint8Array,
outputOffset?: number
): number;
): number; // overload 2
export function encodeBase64(
input: ArrayBuffer | Uint8Array,
inputOffset: number,
output: ArrayBuffer | Uint8Array,
outputOffset?: number
): number;
): number; // overload 3
export function encodeBase64(
input: ArrayBuffer | Uint8Array,
inputOffset: number,
inputLength: number,
output: ArrayBuffer | Uint8Array,
outputOffset?: number
): number;
): number; // overload 4
export function encodeBase64(
input: ArrayBuffer | Uint8Array,
arg1?: number | ArrayBuffer | Uint8Array,
arg2?: number | ArrayBuffer | Uint8Array,
_arg3?: number | ArrayBuffer | Uint8Array,
_arg4?: number,
): ArrayBuffer | Uint8Array | number {
): ArrayBuffer | number {
if (input instanceof ArrayBuffer) {
input = new Uint8Array(input);
}
@ -71,23 +73,27 @@ export function encodeBase64(
let outputOffset: number;
let outputArgumentIndex: number;
if (typeof arg1 !== 'number') {
if (typeof arg1 === 'number') {
// overload 1, 3, 4
inputOffset = arg1;
if (typeof arg2 === 'number') {
// overload 1, 4
inputLength = arg2;
outputArgumentIndex = 3;
} else {
// overload 3
inputLength = input.byteLength - inputOffset;
outputArgumentIndex = 2;
}
} else {
// overload 2
inputOffset = 0;
inputLength = input.byteLength;
outputArgumentIndex = 1;
} else {
inputOffset = arg1;
if (typeof arg2 !== 'number') {
inputLength = input.byteLength - inputOffset;
outputArgumentIndex = 2;
} else {
inputLength = arg2;
outputArgumentIndex = 3;
}
}
const outputLength = calculateBase64EncodedLength(inputLength);
const [outputLength, paddingLength] = calculateBase64EncodedLength(inputLength);
let maybeOutput: ArrayBuffer | Uint8Array | undefined = arguments[outputArgumentIndex];
let outputType: 'ArrayBuffer' | 'number';
@ -134,16 +140,15 @@ export function encodeBase64(
let inputIndex = inputOffset + inputLength - 1;
let outputIndex = outputOffset + outputLength - 1;
const extraBytes = inputLength % 3;
if (extraBytes === 1) {
if (paddingLength === 2) {
// aaaaaabb
const x = input[inputIndex];
inputIndex -= 1;
output[outputIndex] = padding;
output[outputIndex] = paddingChar;
outputIndex -= 1;
output[outputIndex] = padding;
output[outputIndex] = paddingChar;
outputIndex -= 1;
output[outputIndex] = indexToChar[((x & 0b11) << 4)];
@ -151,7 +156,7 @@ export function encodeBase64(
output[outputIndex] = indexToChar[x >> 2];
outputIndex -= 1;
} else if (extraBytes === 2) {
} else if (paddingLength === 1) {
// bbbbcccc
const y = input[inputIndex];
inputIndex -= 1;
@ -160,7 +165,7 @@ export function encodeBase64(
const x = input[inputIndex];
inputIndex -= 1;
output[outputIndex] = padding;
output[outputIndex] = paddingChar;
outputIndex -= 1;
output[outputIndex] = indexToChar[((y & 0b1111) << 2)];