mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2025-02-03 03:59:12 +01:00
55178c76b8
The forth byte of a pixel is undefined in most encodings, so make sure the decoders don't leak that through as an alpha channel.
210 lines
7.6 KiB
JavaScript
210 lines
7.6 KiB
JavaScript
const expect = chai.expect;
|
|
|
|
import Websock from '../core/websock.js';
|
|
import Display from '../core/display.js';
|
|
|
|
import HextileDecoder from '../core/decoders/hextile.js';
|
|
|
|
import FakeWebSocket from './fake.websocket.js';
|
|
|
|
function testDecodeRect(decoder, x, y, width, height, data, display, depth) {
|
|
let sock;
|
|
|
|
sock = new Websock;
|
|
sock.open("ws://example.com");
|
|
|
|
sock.on('message', () => {
|
|
decoder.decodeRect(x, y, width, height, sock, display, depth);
|
|
});
|
|
|
|
sock._websocket._receiveData(new Uint8Array(data));
|
|
|
|
display.flip();
|
|
}
|
|
|
|
function push32(arr, num) {
|
|
arr.push((num >> 24) & 0xFF,
|
|
(num >> 16) & 0xFF,
|
|
(num >> 8) & 0xFF,
|
|
num & 0xFF);
|
|
}
|
|
|
|
describe('Hextile Decoder', function () {
|
|
let decoder;
|
|
let display;
|
|
|
|
before(FakeWebSocket.replace);
|
|
after(FakeWebSocket.restore);
|
|
|
|
beforeEach(function () {
|
|
decoder = new HextileDecoder();
|
|
display = new Display(document.createElement('canvas'));
|
|
display.resize(4, 4);
|
|
});
|
|
|
|
it('should handle a tile with fg, bg specified, normal subrects', function () {
|
|
let data = [];
|
|
data.push(0x02 | 0x04 | 0x08); // bg spec, fg spec, anysubrects
|
|
push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color
|
|
data.push(0xff); // becomes ff000000 --> #0000FF fg color
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(2); // 2 subrects
|
|
data.push(0); // x: 0, y: 0
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
data.push(2 | (2 << 4)); // x: 2, y: 2
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
|
|
testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24);
|
|
|
|
let targetData = new Uint8Array([
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
|
]);
|
|
|
|
expect(display).to.have.displayed(targetData);
|
|
});
|
|
|
|
it('should handle a raw tile', function () {
|
|
let targetData = new Uint8Array([
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
|
]);
|
|
|
|
let data = [];
|
|
data.push(0x01); // raw
|
|
for (let i = 0; i < targetData.length; i += 4) {
|
|
data.push(targetData[i + 2]);
|
|
data.push(targetData[i + 1]);
|
|
data.push(targetData[i]);
|
|
// Last byte zero to test correct alpha handling
|
|
data.push(0);
|
|
}
|
|
|
|
testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24);
|
|
|
|
expect(display).to.have.displayed(targetData);
|
|
});
|
|
|
|
it('should handle a tile with only bg specified (solid bg)', function () {
|
|
let data = [];
|
|
data.push(0x02);
|
|
push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color
|
|
|
|
testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24);
|
|
|
|
let expected = [];
|
|
for (let i = 0; i < 16; i++) {
|
|
push32(expected, 0x00ff00ff);
|
|
}
|
|
|
|
expect(display).to.have.displayed(new Uint8Array(expected));
|
|
});
|
|
|
|
it('should handle a tile with only bg specified and an empty frame afterwards', function () {
|
|
// set the width so we can have two tiles
|
|
display.resize(8, 4);
|
|
|
|
let data = [];
|
|
|
|
// send a bg frame
|
|
data.push(0x02);
|
|
push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color
|
|
|
|
// send an empty frame
|
|
data.push(0x00);
|
|
|
|
testDecodeRect(decoder, 0, 0, 32, 4, data, display, 24);
|
|
|
|
let expected = [];
|
|
for (let i = 0; i < 16; i++) {
|
|
push32(expected, 0x00ff00ff); // rect 1: solid
|
|
}
|
|
for (let i = 0; i < 16; i++) {
|
|
push32(expected, 0x00ff00ff); // rect 2: same bkground color
|
|
}
|
|
|
|
expect(display).to.have.displayed(new Uint8Array(expected));
|
|
});
|
|
|
|
it('should handle a tile with bg and coloured subrects', function () {
|
|
let data = [];
|
|
data.push(0x02 | 0x08 | 0x10); // bg spec, anysubrects, colouredsubrects
|
|
push32(data, 0x00ff0000); // becomes 00ff0000 --> #00FF00 bg color
|
|
data.push(2); // 2 subrects
|
|
data.push(0xff); // becomes ff000000 --> #0000FF fg color
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(0); // x: 0, y: 0
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
data.push(0xff); // becomes ff000000 --> #0000FF fg color
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(2 | (2 << 4)); // x: 2, y: 2
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
|
|
testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24);
|
|
|
|
let targetData = new Uint8Array([
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
|
]);
|
|
|
|
expect(display).to.have.displayed(targetData);
|
|
});
|
|
|
|
it('should carry over fg and bg colors from the previous tile if not specified', function () {
|
|
display.resize(4, 17);
|
|
|
|
let data = [];
|
|
data.push(0x02 | 0x04 | 0x08); // bg spec, fg spec, anysubrects
|
|
push32(data, 0xff00ff); // becomes 00ff00ff --> #00FF00 bg color
|
|
data.push(0xff); // becomes ff0000ff --> #0000FF fg color
|
|
data.push(0x00);
|
|
data.push(0x00);
|
|
data.push(0xff);
|
|
data.push(8); // 8 subrects
|
|
for (let i = 0; i < 4; i++) {
|
|
data.push((0 << 4) | (i * 4)); // x: 0, y: i*4
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
data.push((2 << 4) | (i * 4 + 2)); // x: 2, y: i * 4 + 2
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
}
|
|
data.push(0x08); // anysubrects
|
|
data.push(1); // 1 subrect
|
|
data.push(0); // x: 0, y: 0
|
|
data.push(1 | (1 << 4)); // width: 2, height: 2
|
|
|
|
testDecodeRect(decoder, 0, 0, 4, 17, data, display, 24);
|
|
|
|
let targetData = [
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255, 0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255,
|
|
0x00, 0xff, 0x00, 255, 0x00, 0xff, 0x00, 255, 0x00, 0x00, 0xff, 255, 0x00, 0x00, 0xff, 255
|
|
];
|
|
|
|
let expected = [];
|
|
for (let i = 0; i < 4; i++) {
|
|
expected = expected.concat(targetData);
|
|
}
|
|
expected = expected.concat(targetData.slice(0, 16));
|
|
|
|
expect(display).to.have.displayed(new Uint8Array(expected));
|
|
});
|
|
|
|
it('should fail on an invalid subencoding', function () {
|
|
let data = [45]; // an invalid subencoding
|
|
expect(() => testDecodeRect(decoder, 0, 0, 4, 4, data, display, 24)).to.throw();
|
|
});
|
|
});
|