pdf.js/test/unit/cmap_spec.js
Tim van der Meij 10574a0f8a
Remove obsolete done callbacks from the unit tests
The done callbacks are an outdated mechanism to signal Jasmine that a
unit test is done, mostly in cases where a unit test needed to wait for
an asynchronous operation to complete before doing its assertions.
Nowadays a much better mechanism is in place for that, namely simply
passing an asynchronous function to Jasmine, so we don't need callbacks
anymore (which require more code and may be more difficult to reason
about).

In these particular cases though the done callbacks never had any real
use since nothing asynchronous happens in these places. Synchronous
functions don't need to use done callbacks since Jasmine simply knows
it's done when the function reaches its normal end, so we can safely get
rid of these callbacks. The telltale sign is if the done callback is
used unconditionally at the end of the function.

This is all done in an effort to over time get rid of all callbacks in
the unit test code.
2021-04-10 20:29:39 +02:00

345 lines
10 KiB
JavaScript

/* Copyright 2017 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { CMap, CMapFactory, IdentityCMap } from "../../src/core/cmap.js";
import { CMAP_PARAMS } from "./test_utils.js";
import { DefaultCMapReaderFactory } from "../../src/display/api.js";
import { Name } from "../../src/core/primitives.js";
import { StringStream } from "../../src/core/stream.js";
describe("cmap", function () {
let fetchBuiltInCMap;
beforeAll(function () {
// Allow CMap testing in Node.js, e.g. for Travis.
const CMapReaderFactory = new DefaultCMapReaderFactory({
baseUrl: CMAP_PARAMS.cMapUrl,
isCompressed: CMAP_PARAMS.cMapPacked,
});
fetchBuiltInCMap = function (name) {
return CMapReaderFactory.fetch({
name,
});
};
});
afterAll(function () {
fetchBuiltInCMap = null;
});
it("parses beginbfchar", function (done) {
// prettier-ignore
const str = "2 beginbfchar\n" +
"<03> <00>\n" +
"<04> <01>\n" +
"endbfchar\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.lookup(0x03)).toEqual(String.fromCharCode(0x00));
expect(cmap.lookup(0x04)).toEqual(String.fromCharCode(0x01));
expect(cmap.lookup(0x05)).toBeUndefined();
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("parses beginbfrange with range", function (done) {
// prettier-ignore
const str = "1 beginbfrange\n" +
"<06> <0B> 0\n" +
"endbfrange\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.lookup(0x05)).toBeUndefined();
expect(cmap.lookup(0x06)).toEqual(String.fromCharCode(0x00));
expect(cmap.lookup(0x0b)).toEqual(String.fromCharCode(0x05));
expect(cmap.lookup(0x0c)).toBeUndefined();
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("parses beginbfrange with array", function (done) {
// prettier-ignore
const str = "1 beginbfrange\n" +
"<0D> <12> [ 0 1 2 3 4 5 ]\n" +
"endbfrange\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.lookup(0x0c)).toBeUndefined();
expect(cmap.lookup(0x0d)).toEqual(0x00);
expect(cmap.lookup(0x12)).toEqual(0x05);
expect(cmap.lookup(0x13)).toBeUndefined();
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("parses begincidchar", function (done) {
// prettier-ignore
const str = "1 begincidchar\n" +
"<14> 0\n" +
"endcidchar\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.lookup(0x14)).toEqual(0x00);
expect(cmap.lookup(0x15)).toBeUndefined();
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("parses begincidrange", function (done) {
// prettier-ignore
const str = "1 begincidrange\n" +
"<0016> <001B> 0\n" +
"endcidrange\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.lookup(0x15)).toBeUndefined();
expect(cmap.lookup(0x16)).toEqual(0x00);
expect(cmap.lookup(0x1b)).toEqual(0x05);
expect(cmap.lookup(0x1c)).toBeUndefined();
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("decodes codespace ranges", function (done) {
// prettier-ignore
const str = "1 begincodespacerange\n" +
"<01> <02>\n" +
"<00000003> <00000004>\n" +
"endcodespacerange\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
const c = {};
cmap.readCharCode(String.fromCharCode(1), 0, c);
expect(c.charcode).toEqual(1);
expect(c.length).toEqual(1);
cmap.readCharCode(String.fromCharCode(0, 0, 0, 3), 0, c);
expect(c.charcode).toEqual(3);
expect(c.length).toEqual(4);
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("decodes 4 byte codespace ranges", function (done) {
// prettier-ignore
const str = "1 begincodespacerange\n" +
"<8EA1A1A1> <8EA1FEFE>\n" +
"endcodespacerange\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
const c = {};
cmap.readCharCode(String.fromCharCode(0x8e, 0xa1, 0xa1, 0xa1), 0, c);
expect(c.charcode).toEqual(0x8ea1a1a1);
expect(c.length).toEqual(4);
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("read usecmap", function (done) {
const str = "/Adobe-Japan1-1 usecmap\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({
encoding: stream,
fetchBuiltInCMap,
useCMap: null,
});
cmapPromise
.then(function (cmap) {
expect(cmap instanceof CMap).toEqual(true);
expect(cmap.useCMap).not.toBeNull();
expect(cmap.builtInCMap).toBeFalsy();
expect(cmap.length).toEqual(0x20a7);
expect(cmap.isIdentityCMap).toEqual(false);
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("parses cmapname", function (done) {
const str = "/CMapName /Identity-H def\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.name).toEqual("Identity-H");
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("parses wmode", function (done) {
const str = "/WMode 1 def\n";
const stream = new StringStream(str);
const cmapPromise = CMapFactory.create({ encoding: stream });
cmapPromise
.then(function (cmap) {
expect(cmap.vertical).toEqual(true);
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("loads built in cmap", function (done) {
const cmapPromise = CMapFactory.create({
encoding: Name.get("Adobe-Japan1-1"),
fetchBuiltInCMap,
useCMap: null,
});
cmapPromise
.then(function (cmap) {
expect(cmap instanceof CMap).toEqual(true);
expect(cmap.useCMap).toBeNull();
expect(cmap.builtInCMap).toBeTruthy();
expect(cmap.length).toEqual(0x20a7);
expect(cmap.isIdentityCMap).toEqual(false);
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("loads built in identity cmap", function (done) {
const cmapPromise = CMapFactory.create({
encoding: Name.get("Identity-H"),
fetchBuiltInCMap,
useCMap: null,
});
cmapPromise
.then(function (cmap) {
expect(cmap instanceof IdentityCMap).toEqual(true);
expect(cmap.vertical).toEqual(false);
expect(cmap.length).toEqual(0x10000);
expect(function () {
return cmap.isIdentityCMap;
}).toThrow(new Error("should not access .isIdentityCMap"));
done();
})
.catch(function (reason) {
done.fail(reason);
});
});
it("attempts to load a non-existent built-in CMap", function (done) {
const cmapPromise = CMapFactory.create({
encoding: Name.get("null"),
fetchBuiltInCMap,
useCMap: null,
});
cmapPromise.then(
function () {
done.fail("No CMap should be loaded");
},
function (reason) {
expect(reason instanceof Error).toEqual(true);
expect(reason.message).toEqual("Unknown CMap name: null");
done();
}
);
});
it("attempts to load a built-in CMap without the necessary API parameters", function (done) {
function tmpFetchBuiltInCMap(name) {
const CMapReaderFactory = new DefaultCMapReaderFactory({});
return CMapReaderFactory.fetch({
name,
});
}
const cmapPromise = CMapFactory.create({
encoding: Name.get("Adobe-Japan1-1"),
fetchBuiltInCMap: tmpFetchBuiltInCMap,
useCMap: null,
});
cmapPromise.then(
function () {
done.fail("No CMap should be loaded");
},
function (reason) {
expect(reason instanceof Error).toEqual(true);
expect(reason.message).toEqual(
'The CMap "baseUrl" parameter must be specified, ensure that ' +
'the "cMapUrl" and "cMapPacked" API parameters are provided.'
);
done();
}
);
});
it("attempts to load a built-in CMap with inconsistent API parameters", function (done) {
function tmpFetchBuiltInCMap(name) {
const CMapReaderFactory = new DefaultCMapReaderFactory({
baseUrl: CMAP_PARAMS.cMapUrl,
isCompressed: false,
});
return CMapReaderFactory.fetch({
name,
});
}
const cmapPromise = CMapFactory.create({
encoding: Name.get("Adobe-Japan1-1"),
fetchBuiltInCMap: tmpFetchBuiltInCMap,
useCMap: null,
});
cmapPromise.then(
function () {
done.fail("No CMap should be loaded");
},
function (reason) {
expect(reason instanceof Error).toEqual(true);
const message = reason.message;
expect(message.startsWith("Unable to load CMap at: ")).toEqual(true);
expect(message.endsWith("/external/bcmaps/Adobe-Japan1-1")).toEqual(
true
);
done();
}
);
});
});