mirror of
https://github.com/yume-chan/ya-webadb.git
synced 2025-10-03 09:49:24 +02:00
test(adb): add tests for base64 module
This commit is contained in:
parent
e5f6b34ed0
commit
8b648991e8
9 changed files with 5019 additions and 32 deletions
6
.github/workflows/nodejs.yml
vendored
6
.github/workflows/nodejs.yml
vendored
|
@ -28,6 +28,6 @@ jobs:
|
||||||
env:
|
env:
|
||||||
CI: true
|
CI: true
|
||||||
- run: npm run build --if-present
|
- run: npm run build --if-present
|
||||||
# - run: npm test
|
- run: npm test
|
||||||
# env:
|
env:
|
||||||
# CI: true
|
CI: true
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
"build": "lerna run --scope @yume-chan/adb-backend-web build",
|
"build": "lerna run --scope @yume-chan/adb-backend-web build",
|
||||||
"build:watch": "lerna run --scope @yume-chan/adb-backend-web --stream build:watch",
|
"build:watch": "lerna run --scope @yume-chan/adb-backend-web --stream build:watch",
|
||||||
"build:demo": "lerna run --scope demo --stream build",
|
"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": {
|
"devDependencies": {
|
||||||
"lerna": "3.22.1"
|
"lerna": "3.22.1"
|
||||||
|
|
4
packages/adb/.npmignore
Normal file
4
packages/adb/.npmignore
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
__snapshots__
|
||||||
|
**/*.spec.*
|
||||||
|
jest.config.js
|
||||||
|
tsconfig.tsbuildinfo
|
5
packages/adb/jest.config.js
Normal file
5
packages/adb/jest.config.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
testRegex: 'src/.*/*.spec.tsx?$',
|
||||||
|
testEnvironment: 'node',
|
||||||
|
};
|
4798
packages/adb/package-lock.json
generated
4798
packages/adb/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -15,12 +15,16 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsc -b",
|
"build": "tsc -b",
|
||||||
"build:watch": "tsc -b -w"
|
"build:watch": "tsc -b -w",
|
||||||
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/yume-chan/ya-webadb/issues"
|
"url": "https://github.com/yume-chan/ya-webadb/issues"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/jest": "26.0.19",
|
||||||
|
"jest": "26.6.3",
|
||||||
|
"ts-jest": "26.4.4",
|
||||||
"typescript": "4.1.2"
|
"typescript": "4.1.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|
|
@ -71,7 +71,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
||||||
}
|
}
|
||||||
|
|
||||||
const publicKeyLength = calculatePublicKeyLength();
|
const publicKeyLength = calculatePublicKeyLength();
|
||||||
const publicKeyBase64Length = calculateBase64EncodedLength(publicKeyLength);
|
const [publicKeyBase64Length] = calculateBase64EncodedLength(publicKeyLength);
|
||||||
|
|
||||||
// The public key is null terminated,
|
// The public key is null terminated,
|
||||||
// So we allocate the buffer with one extra byte.
|
// So we allocate the buffer with one extra byte.
|
||||||
|
|
170
packages/adb/src/utils/base64.spec.ts
Normal file
170
packages/adb/src/utils/base64.spec.ts
Normal 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==
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -1,7 +1,7 @@
|
||||||
// Prepare maps for O(1) searching
|
// Prepare maps for O(1) searching
|
||||||
const charToIndex: Record<string, number> = {};
|
const charToIndex: Record<string, number> = {};
|
||||||
const indexToChar: number[] = [];
|
const indexToChar: number[] = [];
|
||||||
const padding = '='.charCodeAt(0);
|
const paddingChar = '='.charCodeAt(0);
|
||||||
|
|
||||||
function addRange(start: string, end: string) {
|
function addRange(start: string, end: string) {
|
||||||
const charCodeStart = start.charCodeAt(0);
|
const charCodeStart = start.charCodeAt(0);
|
||||||
|
@ -20,40 +20,42 @@ addRange('0', '9');
|
||||||
addRange('+', '+');
|
addRange('+', '+');
|
||||||
addRange('/', '/');
|
addRange('/', '/');
|
||||||
|
|
||||||
export function calculateBase64EncodedLength(inputLength: number): number {
|
export function calculateBase64EncodedLength(inputLength: number): [outputLength: number, paddingLength: number] {
|
||||||
return Math.ceil(inputLength / 3) * 4;
|
const remainder = inputLength % 3;
|
||||||
|
const paddingLength = remainder !== 0 ? 3 - remainder : 0;
|
||||||
|
return [(inputLength + paddingLength) / 3 * 4, paddingLength];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodeBase64(
|
export function encodeBase64(
|
||||||
input: ArrayBuffer | Uint8Array,
|
input: ArrayBuffer | Uint8Array,
|
||||||
inputOffset?: number,
|
inputOffset?: number,
|
||||||
inputLength?: number,
|
inputLength?: number,
|
||||||
): ArrayBuffer;
|
): ArrayBuffer; // overload 1
|
||||||
export function encodeBase64(
|
export function encodeBase64(
|
||||||
input: ArrayBuffer | Uint8Array,
|
input: ArrayBuffer | Uint8Array,
|
||||||
output: ArrayBuffer | Uint8Array,
|
output: ArrayBuffer | Uint8Array,
|
||||||
outputOffset?: number
|
outputOffset?: number
|
||||||
): number;
|
): number; // overload 2
|
||||||
export function encodeBase64(
|
export function encodeBase64(
|
||||||
input: ArrayBuffer | Uint8Array,
|
input: ArrayBuffer | Uint8Array,
|
||||||
inputOffset: number,
|
inputOffset: number,
|
||||||
output: ArrayBuffer | Uint8Array,
|
output: ArrayBuffer | Uint8Array,
|
||||||
outputOffset?: number
|
outputOffset?: number
|
||||||
): number;
|
): number; // overload 3
|
||||||
export function encodeBase64(
|
export function encodeBase64(
|
||||||
input: ArrayBuffer | Uint8Array,
|
input: ArrayBuffer | Uint8Array,
|
||||||
inputOffset: number,
|
inputOffset: number,
|
||||||
inputLength: number,
|
inputLength: number,
|
||||||
output: ArrayBuffer | Uint8Array,
|
output: ArrayBuffer | Uint8Array,
|
||||||
outputOffset?: number
|
outputOffset?: number
|
||||||
): number;
|
): number; // overload 4
|
||||||
export function encodeBase64(
|
export function encodeBase64(
|
||||||
input: ArrayBuffer | Uint8Array,
|
input: ArrayBuffer | Uint8Array,
|
||||||
arg1?: number | ArrayBuffer | Uint8Array,
|
arg1?: number | ArrayBuffer | Uint8Array,
|
||||||
arg2?: number | ArrayBuffer | Uint8Array,
|
arg2?: number | ArrayBuffer | Uint8Array,
|
||||||
_arg3?: number | ArrayBuffer | Uint8Array,
|
_arg3?: number | ArrayBuffer | Uint8Array,
|
||||||
_arg4?: number,
|
_arg4?: number,
|
||||||
): ArrayBuffer | Uint8Array | number {
|
): ArrayBuffer | number {
|
||||||
if (input instanceof ArrayBuffer) {
|
if (input instanceof ArrayBuffer) {
|
||||||
input = new Uint8Array(input);
|
input = new Uint8Array(input);
|
||||||
}
|
}
|
||||||
|
@ -71,23 +73,27 @@ export function encodeBase64(
|
||||||
let outputOffset: number;
|
let outputOffset: number;
|
||||||
|
|
||||||
let outputArgumentIndex: 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;
|
inputOffset = 0;
|
||||||
inputLength = input.byteLength;
|
inputLength = input.byteLength;
|
||||||
outputArgumentIndex = 1;
|
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 maybeOutput: ArrayBuffer | Uint8Array | undefined = arguments[outputArgumentIndex];
|
||||||
let outputType: 'ArrayBuffer' | 'number';
|
let outputType: 'ArrayBuffer' | 'number';
|
||||||
|
@ -134,16 +140,15 @@ export function encodeBase64(
|
||||||
let inputIndex = inputOffset + inputLength - 1;
|
let inputIndex = inputOffset + inputLength - 1;
|
||||||
let outputIndex = outputOffset + outputLength - 1;
|
let outputIndex = outputOffset + outputLength - 1;
|
||||||
|
|
||||||
const extraBytes = inputLength % 3;
|
if (paddingLength === 2) {
|
||||||
if (extraBytes === 1) {
|
|
||||||
// aaaaaabb
|
// aaaaaabb
|
||||||
const x = input[inputIndex];
|
const x = input[inputIndex];
|
||||||
inputIndex -= 1;
|
inputIndex -= 1;
|
||||||
|
|
||||||
output[outputIndex] = padding;
|
output[outputIndex] = paddingChar;
|
||||||
outputIndex -= 1;
|
outputIndex -= 1;
|
||||||
|
|
||||||
output[outputIndex] = padding;
|
output[outputIndex] = paddingChar;
|
||||||
outputIndex -= 1;
|
outputIndex -= 1;
|
||||||
|
|
||||||
output[outputIndex] = indexToChar[((x & 0b11) << 4)];
|
output[outputIndex] = indexToChar[((x & 0b11) << 4)];
|
||||||
|
@ -151,7 +156,7 @@ export function encodeBase64(
|
||||||
|
|
||||||
output[outputIndex] = indexToChar[x >> 2];
|
output[outputIndex] = indexToChar[x >> 2];
|
||||||
outputIndex -= 1;
|
outputIndex -= 1;
|
||||||
} else if (extraBytes === 2) {
|
} else if (paddingLength === 1) {
|
||||||
// bbbbcccc
|
// bbbbcccc
|
||||||
const y = input[inputIndex];
|
const y = input[inputIndex];
|
||||||
inputIndex -= 1;
|
inputIndex -= 1;
|
||||||
|
@ -160,7 +165,7 @@ export function encodeBase64(
|
||||||
const x = input[inputIndex];
|
const x = input[inputIndex];
|
||||||
inputIndex -= 1;
|
inputIndex -= 1;
|
||||||
|
|
||||||
output[outputIndex] = padding;
|
output[outputIndex] = paddingChar;
|
||||||
outputIndex -= 1;
|
outputIndex -= 1;
|
||||||
|
|
||||||
output[outputIndex] = indexToChar[((y & 0b1111) << 2)];
|
output[outputIndex] = indexToChar[((y & 0b1111) << 2)];
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue