run prettier on js/test; add prettier check to CI

This commit is contained in:
Brandon Liu
2023-03-12 13:30:57 +08:00
parent 606c80a1fc
commit 802f6aea4e
5 changed files with 414 additions and 400 deletions

View File

@@ -44,6 +44,7 @@ jobs:
node-version: 18.x node-version: 18.x
- run: python .github/check_examples.py - run: python .github/check_examples.py
- run: cd js && npm install && npm test - run: cd js && npm install && npm test
- run: cd js && npm prettier-check
- run: cd python && python -m unittest test/test_* - run: cd python && python -m unittest test/test_*
- run: cd cpp && make - run: cd cpp && make
- run: cd serverless/cloudflare && npm install && npm test - run: cd serverless/cloudflare && npm install && npm test

View File

@@ -18,7 +18,8 @@
"build": "npm run build-iife && npm run build-esm && npm run build-cjs && npm run build-tsc", "build": "npm run build-iife && npm run build-esm && npm run build-cjs && npm run build-tsc",
"test": "node -r esbuild-runner/register test/index.test.ts", "test": "node -r esbuild-runner/register test/index.test.ts",
"tsc": "tsc --noEmit --watch", "tsc": "tsc --noEmit --watch",
"prettier": "prettier --write *.ts" "prettier": "prettier --write *.ts test/*.ts",
"prettier-check": "prettier --check *.ts test/*.ts"
}, },
"homepage": "https://github.com/protomaps/pmtiles", "homepage": "https://github.com/protomaps/pmtiles",
"author": "Brandon Liu", "author": "Brandon Liu",

View File

@@ -1,2 +1,2 @@
import './v2.test'; import "./v2.test";
import './v3.test'; import "./v3.test";

View File

@@ -14,137 +14,149 @@ import {
} from "../v2"; } from "../v2";
test("stub data", () => { test("stub data", () => {
let dataview = new DataView(createDirectory([ let dataview = new DataView(
{ z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false }, createDirectory([
{ { z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false },
z: 14, {
x: 16383, z: 14,
y: 16383, x: 16383,
offset: 999999, y: 16383,
length: 999, offset: 999999,
is_dir: false, length: 999,
}, is_dir: false,
])); },
])
);
var z_raw = dataview.getUint8(17 + 0); var z_raw = dataview.getUint8(17 + 0);
var x = getUint24(dataview, 17 + 1); var x = getUint24(dataview, 17 + 1);
var y = getUint24(dataview, 17 + 4); var y = getUint24(dataview, 17 + 4);
var offset = getUint48(dataview, 17 + 7); var offset = getUint48(dataview, 17 + 7);
var length = dataview.getUint32(17 + 13, true); var length = dataview.getUint32(17 + 13, true);
assert.strictEqual(z_raw,14); assert.strictEqual(z_raw, 14);
assert.strictEqual(x,16383); assert.strictEqual(x, 16383);
assert.strictEqual(y,16383); assert.strictEqual(y, 16383);
}); });
test("get entry", () => { test("get entry", () => {
let view = new DataView(createDirectory([ let view = new DataView(
{ z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false }, createDirectory([
{ { z: 5, x: 1000, y: 2000, offset: 1000, length: 2000, is_dir: false },
z: 14, {
x: 16383, z: 14,
y: 16383, x: 16383,
offset: 999999, y: 16383,
length: 999, offset: 999999,
is_dir: false, length: 999,
}, is_dir: false,
])); },
])
);
let entry = queryTile(view, 14, 16383, 16383); let entry = queryTile(view, 14, 16383, 16383);
assert.strictEqual(entry!.z,14); assert.strictEqual(entry!.z, 14);
assert.strictEqual(entry!.x,16383); assert.strictEqual(entry!.x, 16383);
assert.strictEqual(entry!.y,16383); assert.strictEqual(entry!.y, 16383);
assert.strictEqual(entry!.offset,999999); assert.strictEqual(entry!.offset, 999999);
assert.strictEqual(entry!.length,999); assert.strictEqual(entry!.length, 999);
assert.strictEqual(entry!.is_dir,false); assert.strictEqual(entry!.is_dir, false);
assert.strictEqual(queryLeafdir(view, 14, 16383, 16383),null); assert.strictEqual(queryLeafdir(view, 14, 16383, 16383), null);
}); });
test("get leafdir", () => { test("get leafdir", () => {
let view = new DataView(createDirectory([ let view = new DataView(
{ createDirectory([
z: 14, {
x: 16383, z: 14,
y: 16383, x: 16383,
offset: 999999, y: 16383,
length: 999, offset: 999999,
is_dir: true, length: 999,
}, is_dir: true,
])); },
])
);
let entry = queryLeafdir(view, 14, 16383, 16383); let entry = queryLeafdir(view, 14, 16383, 16383);
assert.strictEqual(entry!.z,14); assert.strictEqual(entry!.z, 14);
assert.strictEqual(entry!.x,16383); assert.strictEqual(entry!.x, 16383);
assert.strictEqual(entry!.y,16383); assert.strictEqual(entry!.y, 16383);
assert.strictEqual(entry!.offset,999999); assert.strictEqual(entry!.offset, 999999);
assert.strictEqual(entry!.length,999); assert.strictEqual(entry!.length, 999);
assert.strictEqual(entry!.is_dir,true); assert.strictEqual(entry!.is_dir, true);
assert.strictEqual(queryTile(view, 14, 16383, 16383),null); assert.strictEqual(queryTile(view, 14, 16383, 16383), null);
}); });
test("derive the leaf level", () => { test("derive the leaf level", () => {
let view = new DataView(createDirectory([ let view = new DataView(
{ createDirectory([
z: 6, {
x: 3, z: 6,
y: 3, x: 3,
offset: 0, y: 3,
length: 0, offset: 0,
is_dir: true, length: 0,
}, is_dir: true,
])); },
let leaf = deriveLeaf(view,{z:7,x:6,y:6}); ])
assert.strictEqual(leaf!.z,6); );
assert.strictEqual(leaf!.x,3); let leaf = deriveLeaf(view, { z: 7, x: 6, y: 6 });
assert.strictEqual(leaf!.y,3); assert.strictEqual(leaf!.z, 6);
view = new DataView(createDirectory([ assert.strictEqual(leaf!.x, 3);
{ assert.strictEqual(leaf!.y, 3);
z: 6, view = new DataView(
x: 3, createDirectory([
y: 3, {
offset: 0, z: 6,
length: 0, x: 3,
is_dir: false, y: 3,
}, offset: 0,
])); length: 0,
leaf = deriveLeaf(view,{z:7,x:6,y:6}); is_dir: false,
assert.strictEqual(leaf,null); },
])
);
leaf = deriveLeaf(view, { z: 7, x: 6, y: 6 });
assert.strictEqual(leaf, null);
}); });
test("convert spec v1 directory to spec v2 directory", () => { test("convert spec v1 directory to spec v2 directory", () => {
let view = new DataView(createDirectory([ let view = new DataView(
{ createDirectory([
z: 7, {
x: 3, z: 7,
y: 3, x: 3,
offset: 3, y: 3,
length: 3, offset: 3,
is_dir: true, length: 3,
}, is_dir: true,
{ },
z: 6, {
x: 2, z: 6,
y: 2, x: 2,
offset: 2, y: 2,
length: 2, offset: 2,
is_dir: false, length: 2,
}, is_dir: false,
{ },
z: 6, {
x: 2, z: 6,
y: 1, x: 2,
offset: 1, y: 1,
length: 1, offset: 1,
is_dir: false, length: 1,
}, is_dir: false,
])); },
])
);
let entry = queryLeafdir(view, 7, 3, 3); let entry = queryLeafdir(view, 7, 3, 3);
assert.strictEqual(entry!.offset,3); assert.strictEqual(entry!.offset, 3);
entry = queryTile(view, 6, 2, 2); entry = queryTile(view, 6, 2, 2);
assert.strictEqual(entry!.offset,2); assert.strictEqual(entry!.offset, 2);
entry = queryTile(view, 6, 2, 1); entry = queryTile(view, 6, 2, 1);
assert.strictEqual(entry!.offset,1); assert.strictEqual(entry!.offset, 1);
entry = parseEntry(view, 0); entry = parseEntry(view, 0);
assert.strictEqual(entry!.offset,1); assert.strictEqual(entry!.offset, 1);
entry = parseEntry(view, 1); entry = parseEntry(view, 1);
assert.strictEqual(entry!.offset,2); assert.strictEqual(entry!.offset, 2);
entry = parseEntry(view, 2); entry = parseEntry(view, 2);
assert.strictEqual(entry!.offset,3); assert.strictEqual(entry!.offset, 3);
}); });

View File

@@ -3,389 +3,389 @@ import assert from "node:assert";
import fs from "fs"; import fs from "fs";
import { import {
Entry, Entry,
zxyToTileId, zxyToTileId,
tileIdToZxy, tileIdToZxy,
findTile, findTile,
readVarint, readVarint,
SharedPromiseCache, SharedPromiseCache,
BufferPosition, BufferPosition,
Source, Source,
RangeResponse, RangeResponse,
EtagMismatch, EtagMismatch,
PMTiles, PMTiles,
getUint64, getUint64,
} from "../index"; } from "../index";
test("varint", () => { test("varint", () => {
let b: BufferPosition = { let b: BufferPosition = {
buf: new Uint8Array([0, 1, 127, 0xe5, 0x8e, 0x26]), buf: new Uint8Array([0, 1, 127, 0xe5, 0x8e, 0x26]),
pos: 0, pos: 0,
}; };
assert.strictEqual(readVarint(b), 0); assert.strictEqual(readVarint(b), 0);
assert.strictEqual(readVarint(b), 1); assert.strictEqual(readVarint(b), 1);
assert.strictEqual(readVarint(b), 127); assert.strictEqual(readVarint(b), 127);
assert.strictEqual(readVarint(b), 624485); assert.strictEqual(readVarint(b), 624485);
b = { b = {
buf: new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f]), buf: new Uint8Array([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f]),
pos: 0, pos: 0,
}; };
assert.strictEqual(readVarint(b), 9007199254740991); assert.strictEqual(readVarint(b), 9007199254740991);
}); });
test("zxy to tile id", () => { test("zxy to tile id", () => {
assert.strictEqual(zxyToTileId(0, 0, 0), 0); assert.strictEqual(zxyToTileId(0, 0, 0), 0);
assert.strictEqual(zxyToTileId(1, 0, 0), 1); assert.strictEqual(zxyToTileId(1, 0, 0), 1);
assert.strictEqual(zxyToTileId(1, 0, 1), 2); assert.strictEqual(zxyToTileId(1, 0, 1), 2);
assert.strictEqual(zxyToTileId(1, 1, 1), 3); assert.strictEqual(zxyToTileId(1, 1, 1), 3);
assert.strictEqual(zxyToTileId(1, 1, 0), 4); assert.strictEqual(zxyToTileId(1, 1, 0), 4);
assert.strictEqual(zxyToTileId(2, 0, 0), 5); assert.strictEqual(zxyToTileId(2, 0, 0), 5);
}); });
test("tile id to zxy", () => { test("tile id to zxy", () => {
assert.deepEqual(tileIdToZxy(0), [0, 0, 0]); assert.deepEqual(tileIdToZxy(0), [0, 0, 0]);
assert.deepEqual(tileIdToZxy(1), [1, 0, 0]); assert.deepEqual(tileIdToZxy(1), [1, 0, 0]);
assert.deepEqual(tileIdToZxy(2), [1, 0, 1]); assert.deepEqual(tileIdToZxy(2), [1, 0, 1]);
assert.deepEqual(tileIdToZxy(3), [1, 1, 1]); assert.deepEqual(tileIdToZxy(3), [1, 1, 1]);
assert.deepEqual(tileIdToZxy(4), [1, 1, 0]); assert.deepEqual(tileIdToZxy(4), [1, 1, 0]);
assert.deepEqual(tileIdToZxy(5), [2, 0, 0]); assert.deepEqual(tileIdToZxy(5), [2, 0, 0]);
}); });
test("a lot of tiles", () => { test("a lot of tiles", () => {
for (let z = 0; z < 9; z++) { for (let z = 0; z < 9; z++) {
for (let x = 0; x < 1 << z; x++) { for (let x = 0; x < 1 << z; x++) {
for (let y = 0; y < 1 << z; y++) { for (let y = 0; y < 1 << z; y++) {
const result = tileIdToZxy(zxyToTileId(z, x, y)); const result = tileIdToZxy(zxyToTileId(z, x, y));
if (result[0] !== z || result[1] !== x || result[2] !== y) { if (result[0] !== z || result[1] !== x || result[2] !== y) {
assert.fail("roundtrip failed"); assert.fail("roundtrip failed");
} }
} }
} }
} }
}); });
test("tile extremes", () => { test("tile extremes", () => {
for (var z = 0; z < 27; z++) { for (var z = 0; z < 27; z++) {
const dim = Math.pow(2, z) - 1; const dim = Math.pow(2, z) - 1;
const tl = tileIdToZxy(zxyToTileId(z, 0, 0)); const tl = tileIdToZxy(zxyToTileId(z, 0, 0));
assert.deepEqual([z, 0, 0], tl); assert.deepEqual([z, 0, 0], tl);
const tr = tileIdToZxy(zxyToTileId(z, dim, 0)); const tr = tileIdToZxy(zxyToTileId(z, dim, 0));
assert.deepEqual([z, dim, 0], tr); assert.deepEqual([z, dim, 0], tr);
const bl = tileIdToZxy(zxyToTileId(z, 0, dim)); const bl = tileIdToZxy(zxyToTileId(z, 0, dim));
assert.deepEqual([z, 0, dim], bl); assert.deepEqual([z, 0, dim], bl);
const br = tileIdToZxy(zxyToTileId(z, dim, dim)); const br = tileIdToZxy(zxyToTileId(z, dim, dim));
assert.deepEqual([z, dim, dim], br); assert.deepEqual([z, dim, dim], br);
} }
}); });
test("invalid tiles", () => { test("invalid tiles", () => {
assert.throws(() => { assert.throws(() => {
tileIdToZxy(Number.MAX_SAFE_INTEGER); tileIdToZxy(Number.MAX_SAFE_INTEGER);
}); });
assert.throws(() => { assert.throws(() => {
zxyToTileId(27,0,0); zxyToTileId(27, 0, 0);
}); });
assert.throws(() => { assert.throws(() => {
zxyToTileId(0,1,1); zxyToTileId(0, 1, 1);
}); });
}); });
test("tile search for missing entry", () => { test("tile search for missing entry", () => {
const entries: Entry[] = []; const entries: Entry[] = [];
assert.strictEqual(findTile(entries, 101), null); assert.strictEqual(findTile(entries, 101), null);
}); });
test("tile search for first entry == id", () => { test("tile search for first entry == id", () => {
const entries: Entry[] = [ const entries: Entry[] = [
{ tileId: 100, offset: 1, length: 1, runLength: 1 }, { tileId: 100, offset: 1, length: 1, runLength: 1 },
]; ];
const entry = findTile(entries, 100)!; const entry = findTile(entries, 100)!;
assert.strictEqual(entry.offset, 1); assert.strictEqual(entry.offset, 1);
assert.strictEqual(entry.length, 1); assert.strictEqual(entry.length, 1);
assert.strictEqual(findTile(entries, 101), null); assert.strictEqual(findTile(entries, 101), null);
}); });
test("tile search with runlength", () => { test("tile search with runlength", () => {
const entries: Entry[] = [ const entries: Entry[] = [
{ tileId: 3, offset: 3, length: 1, runLength: 2 }, { tileId: 3, offset: 3, length: 1, runLength: 2 },
{ tileId: 5, offset: 5, length: 1, runLength: 2 }, { tileId: 5, offset: 5, length: 1, runLength: 2 },
]; ];
const entry = findTile(entries, 4)!; const entry = findTile(entries, 4)!;
assert.strictEqual(entry.offset, 3); assert.strictEqual(entry.offset, 3);
}); });
test("tile search with multiple tile entries", () => { test("tile search with multiple tile entries", () => {
let entries: Entry[] = [{ tileId: 100, offset: 1, length: 1, runLength: 2 }]; let entries: Entry[] = [{ tileId: 100, offset: 1, length: 1, runLength: 2 }];
let entry = findTile(entries, 101)!; let entry = findTile(entries, 101)!;
assert.strictEqual(entry.offset, 1); assert.strictEqual(entry.offset, 1);
assert.strictEqual(entry.length, 1); assert.strictEqual(entry.length, 1);
entries = [ entries = [
{ tileId: 100, offset: 1, length: 1, runLength: 1 }, { tileId: 100, offset: 1, length: 1, runLength: 1 },
{ tileId: 150, offset: 2, length: 2, runLength: 2 }, { tileId: 150, offset: 2, length: 2, runLength: 2 },
]; ];
entry = findTile(entries, 151)!; entry = findTile(entries, 151)!;
assert.strictEqual(entry.offset, 2); assert.strictEqual(entry.offset, 2);
assert.strictEqual(entry.length, 2); assert.strictEqual(entry.length, 2);
entries = [ entries = [
{ tileId: 50, offset: 1, length: 1, runLength: 2 }, { tileId: 50, offset: 1, length: 1, runLength: 2 },
{ tileId: 100, offset: 2, length: 2, runLength: 1 }, { tileId: 100, offset: 2, length: 2, runLength: 1 },
{ tileId: 150, offset: 3, length: 3, runLength: 1 }, { tileId: 150, offset: 3, length: 3, runLength: 1 },
]; ];
entry = findTile(entries, 51)!; entry = findTile(entries, 51)!;
assert.strictEqual(entry.offset, 1); assert.strictEqual(entry.offset, 1);
assert.strictEqual(entry.length, 1); assert.strictEqual(entry.length, 1);
}); });
test("leaf search", () => { test("leaf search", () => {
const entries: Entry[] = [ const entries: Entry[] = [
{ tileId: 100, offset: 1, length: 1, runLength: 0 }, { tileId: 100, offset: 1, length: 1, runLength: 0 },
]; ];
const entry = findTile(entries, 150); const entry = findTile(entries, 150);
assert.strictEqual(entry!.offset, 1); assert.strictEqual(entry!.offset, 1);
assert.strictEqual(entry!.length, 1); assert.strictEqual(entry!.length, 1);
}); });
// inefficient method only for testing // inefficient method only for testing
class TestNodeFileSource implements Source { class TestNodeFileSource implements Source {
buffer: ArrayBuffer; buffer: ArrayBuffer;
path: string; path: string;
key: string; key: string;
etag?: string; etag?: string;
constructor(path: string, key: string) { constructor(path: string, key: string) {
this.path = path; this.path = path;
this.buffer = fs.readFileSync(path); this.buffer = fs.readFileSync(path);
this.key = key; this.key = key;
} }
getKey() { getKey() {
return this.key; return this.key;
} }
replaceData(path: string) { replaceData(path: string) {
this.path = path; this.path = path;
this.buffer = fs.readFileSync(path); this.buffer = fs.readFileSync(path);
} }
async getBytes(offset: number, length: number): Promise<RangeResponse> { async getBytes(offset: number, length: number): Promise<RangeResponse> {
const slice = new Uint8Array(this.buffer.slice(offset, offset + length)) const slice = new Uint8Array(this.buffer.slice(offset, offset + length))
.buffer; .buffer;
return { data: slice, etag: this.etag }; return { data: slice, etag: this.etag };
} }
} }
// echo '{"type":"Polygon","coordinates":[[[0,0],[0,1],[1,1],[1,0],[0,0]]]}' | ./tippecanoe -zg -o test_fixture_1.pmtiles // echo '{"type":"Polygon","coordinates":[[[0,0],[0,1],[1,1],[1,0],[0,0]]]}' | ./tippecanoe -zg -o test_fixture_1.pmtiles
test("cache getHeader", async () => { test("cache getHeader", async () => {
const source = new TestNodeFileSource( const source = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
const cache = new SharedPromiseCache(); const cache = new SharedPromiseCache();
const header = await cache.getHeader(source); const header = await cache.getHeader(source);
assert.strictEqual(header.rootDirectoryOffset, 127); assert.strictEqual(header.rootDirectoryOffset, 127);
assert.strictEqual(header.rootDirectoryLength, 25); assert.strictEqual(header.rootDirectoryLength, 25);
assert.strictEqual(header.jsonMetadataOffset, 152); assert.strictEqual(header.jsonMetadataOffset, 152);
assert.strictEqual(header.jsonMetadataLength, 247); assert.strictEqual(header.jsonMetadataLength, 247);
assert.strictEqual(header.leafDirectoryOffset, 0); assert.strictEqual(header.leafDirectoryOffset, 0);
assert.strictEqual(header.leafDirectoryLength, 0); assert.strictEqual(header.leafDirectoryLength, 0);
assert.strictEqual(header.tileDataOffset, 399); assert.strictEqual(header.tileDataOffset, 399);
assert.strictEqual(header.tileDataLength, 69); assert.strictEqual(header.tileDataLength, 69);
assert.strictEqual(header.numAddressedTiles, 1); assert.strictEqual(header.numAddressedTiles, 1);
assert.strictEqual(header.numTileEntries, 1); assert.strictEqual(header.numTileEntries, 1);
assert.strictEqual(header.numTileContents, 1); assert.strictEqual(header.numTileContents, 1);
assert.strictEqual(header.clustered, false); assert.strictEqual(header.clustered, false);
assert.strictEqual(header.internalCompression, 2); assert.strictEqual(header.internalCompression, 2);
assert.strictEqual(header.tileCompression, 2); assert.strictEqual(header.tileCompression, 2);
assert.strictEqual(header.tileType, 1); assert.strictEqual(header.tileType, 1);
assert.strictEqual(header.minZoom, 0); assert.strictEqual(header.minZoom, 0);
assert.strictEqual(header.maxZoom, 0); assert.strictEqual(header.maxZoom, 0);
assert.strictEqual(header.minLon, 0); assert.strictEqual(header.minLon, 0);
assert.strictEqual(header.minLat, 0); assert.strictEqual(header.minLat, 0);
// assert.strictEqual(header.maxLon,1); // TODO fix me // assert.strictEqual(header.maxLon,1); // TODO fix me
assert.strictEqual(header.maxLat, 1); assert.strictEqual(header.maxLat, 1);
}); });
test("getUint64", async () => { test("getUint64", async () => {
const view = new DataView(new ArrayBuffer(8)); const view = new DataView(new ArrayBuffer(8));
view.setBigUint64(0, 0n, true); view.setBigUint64(0, 0n, true);
assert.strictEqual(getUint64(view, 0), 0); assert.strictEqual(getUint64(view, 0), 0);
view.setBigUint64(0, 1n, true); view.setBigUint64(0, 1n, true);
assert.strictEqual(getUint64(view, 0), 1); assert.strictEqual(getUint64(view, 0), 1);
view.setBigUint64(0, 9007199254740991n, true); view.setBigUint64(0, 9007199254740991n, true);
assert.strictEqual(getUint64(view, 0), 9007199254740991); assert.strictEqual(getUint64(view, 0), 9007199254740991);
}); });
test("cache check against empty", async () => { test("cache check against empty", async () => {
const source = new TestNodeFileSource("test/data/empty.pmtiles", "1"); const source = new TestNodeFileSource("test/data/empty.pmtiles", "1");
const cache = new SharedPromiseCache(); const cache = new SharedPromiseCache();
assert.rejects(async () => { assert.rejects(async () => {
await cache.getHeader(source); await cache.getHeader(source);
}); });
}); });
test("cache check magic number", async () => { test("cache check magic number", async () => {
const source = new TestNodeFileSource("test/data/invalid.pmtiles", "1"); const source = new TestNodeFileSource("test/data/invalid.pmtiles", "1");
const cache = new SharedPromiseCache(); const cache = new SharedPromiseCache();
assert.rejects(async () => { assert.rejects(async () => {
await cache.getHeader(source); await cache.getHeader(source);
}); });
}); });
test("cache check future spec version", async () => { test("cache check future spec version", async () => {
const source = new TestNodeFileSource("test/data/invalid_v4.pmtiles", "1"); const source = new TestNodeFileSource("test/data/invalid_v4.pmtiles", "1");
const cache = new SharedPromiseCache(); const cache = new SharedPromiseCache();
assert.rejects(async () => { assert.rejects(async () => {
await cache.getHeader(source); await cache.getHeader(source);
}); });
}); });
test("cache getDirectory", async () => { test("cache getDirectory", async () => {
const source = new TestNodeFileSource( const source = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
let cache = new SharedPromiseCache(6400, false); let cache = new SharedPromiseCache(6400, false);
let header = await cache.getHeader(source); let header = await cache.getHeader(source);
assert.strictEqual(cache.cache.size, 1); assert.strictEqual(cache.cache.size, 1);
cache = new SharedPromiseCache(6400, true); cache = new SharedPromiseCache(6400, true);
header = await cache.getHeader(source); header = await cache.getHeader(source);
// prepopulates the root directory // prepopulates the root directory
assert.strictEqual(cache.cache.size, 2); assert.strictEqual(cache.cache.size, 2);
const directory = await cache.getDirectory( const directory = await cache.getDirectory(
source, source,
header.rootDirectoryOffset, header.rootDirectoryOffset,
header.rootDirectoryLength, header.rootDirectoryLength,
header header
); );
assert.strictEqual(directory.length, 1); assert.strictEqual(directory.length, 1);
assert.strictEqual(directory[0].tileId, 0); assert.strictEqual(directory[0].tileId, 0);
assert.strictEqual(directory[0].offset, 0); assert.strictEqual(directory[0].offset, 0);
assert.strictEqual(directory[0].length, 69); assert.strictEqual(directory[0].length, 69);
assert.strictEqual(directory[0].runLength, 1); assert.strictEqual(directory[0].runLength, 1);
for (const v of cache.cache.values()) { for (const v of cache.cache.values()) {
assert.ok(v.lastUsed > 0); assert.ok(v.lastUsed > 0);
} }
}); });
test("multiple sources in a single cache", async () => { test("multiple sources in a single cache", async () => {
const cache = new SharedPromiseCache(); const cache = new SharedPromiseCache();
const source1 = new TestNodeFileSource( const source1 = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
const source2 = new TestNodeFileSource( const source2 = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"2" "2"
); );
await cache.getHeader(source1); await cache.getHeader(source1);
assert.strictEqual(cache.cache.size, 2); assert.strictEqual(cache.cache.size, 2);
await cache.getHeader(source2); await cache.getHeader(source2);
assert.strictEqual(cache.cache.size, 4); assert.strictEqual(cache.cache.size, 4);
}); });
test("etags are part of key", async () => { test("etags are part of key", async () => {
const cache = new SharedPromiseCache(6400, false); const cache = new SharedPromiseCache(6400, false);
const source = new TestNodeFileSource( const source = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
source.etag = "etag_1"; source.etag = "etag_1";
let header = await cache.getHeader(source); let header = await cache.getHeader(source);
assert.strictEqual(header.etag, "etag_1"); assert.strictEqual(header.etag, "etag_1");
source.etag = "etag_2"; source.etag = "etag_2";
assert.rejects(async () => { assert.rejects(async () => {
await cache.getDirectory( await cache.getDirectory(
source, source,
header.rootDirectoryOffset, header.rootDirectoryOffset,
header.rootDirectoryLength, header.rootDirectoryLength,
header header
); );
}) });
cache.invalidate(source, "etag_2"); cache.invalidate(source, "etag_2");
header = await cache.getHeader(source); header = await cache.getHeader(source);
assert.ok( assert.ok(
await cache.getDirectory( await cache.getDirectory(
source, source,
header.rootDirectoryOffset, header.rootDirectoryOffset,
header.rootDirectoryLength, header.rootDirectoryLength,
header header
) )
); );
}); });
test("soft failure on etag weirdness", async () => { test("soft failure on etag weirdness", async () => {
const cache = new SharedPromiseCache(6400, false); const cache = new SharedPromiseCache(6400, false);
const source = new TestNodeFileSource( const source = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
source.etag = "etag_1"; source.etag = "etag_1";
let header = await cache.getHeader(source); let header = await cache.getHeader(source);
assert.strictEqual(header.etag, "etag_1"); assert.strictEqual(header.etag, "etag_1");
source.etag = "etag_2"; source.etag = "etag_2";
assert.rejects(async () => { assert.rejects(async () => {
await cache.getDirectory( await cache.getDirectory(
source, source,
header.rootDirectoryOffset, header.rootDirectoryOffset,
header.rootDirectoryLength, header.rootDirectoryLength,
header header
); );
}) });
source.etag = "etag_1"; source.etag = "etag_1";
cache.invalidate(source, "etag_2"); cache.invalidate(source, "etag_2");
header = await cache.getHeader(source); header = await cache.getHeader(source);
assert.strictEqual(header.etag, undefined); assert.strictEqual(header.etag, undefined);
}); });
test("cache pruning by byte size", async () => { test("cache pruning by byte size", async () => {
const cache = new SharedPromiseCache(2, false); const cache = new SharedPromiseCache(2, false);
cache.cache.set("0", { lastUsed: 0, data: Promise.resolve([]) }); cache.cache.set("0", { lastUsed: 0, data: Promise.resolve([]) });
cache.cache.set("1", { lastUsed: 1, data: Promise.resolve([]) }); cache.cache.set("1", { lastUsed: 1, data: Promise.resolve([]) });
cache.cache.set("2", { lastUsed: 2, data: Promise.resolve([]) }); cache.cache.set("2", { lastUsed: 2, data: Promise.resolve([]) });
cache.prune(); cache.prune();
assert.strictEqual(cache.cache.size, 2); assert.strictEqual(cache.cache.size, 2);
assert.ok(cache.cache.get("2")); assert.ok(cache.cache.get("2"));
assert.ok(cache.cache.get("1")); assert.ok(cache.cache.get("1"));
assert.ok(!cache.cache.get("0")); assert.ok(!cache.cache.get("0"));
}); });
test("pmtiles get metadata", async () => { test("pmtiles get metadata", async () => {
const source = new TestNodeFileSource( const source = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
const p = new PMTiles(source); const p = new PMTiles(source);
const metadata = await p.getMetadata(); const metadata = await p.getMetadata();
assert.ok(metadata.name); assert.ok(metadata.name);
}); });
// echo '{"type":"Polygon","coordinates":[[[0,0],[0,1],[1,0],[0,0]]]}' | ./tippecanoe -zg -o test_fixture_2.pmtiles // echo '{"type":"Polygon","coordinates":[[[0,0],[0,1],[1,0],[0,0]]]}' | ./tippecanoe -zg -o test_fixture_2.pmtiles
test("pmtiles handle retries", async () => { test("pmtiles handle retries", async () => {
const source = new TestNodeFileSource( const source = new TestNodeFileSource(
"test/data/test_fixture_1.pmtiles", "test/data/test_fixture_1.pmtiles",
"1" "1"
); );
source.etag = "1"; source.etag = "1";
const p = new PMTiles(source); const p = new PMTiles(source);
const metadata = await p.getMetadata(); const metadata = await p.getMetadata();
assert.ok(metadata.name); assert.ok(metadata.name);
source.etag = "2"; source.etag = "2";
source.replaceData("test/data/test_fixture_2.pmtiles"); source.replaceData("test/data/test_fixture_2.pmtiles");
assert.ok(await p.getZxy(0, 0, 0)); assert.ok(await p.getZxy(0, 0, 0));
}); });