mirror of
https://github.com/protomaps/PMTiles.git
synced 2026-02-04 10:51:07 +00:00
run prettier on js/test; add prettier check to CI
This commit is contained in:
1
.github/workflows/actions.yml
vendored
1
.github/workflows/actions.yml
vendored
@@ -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
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
import './v2.test';
|
import "./v2.test";
|
||||||
import './v3.test';
|
import "./v3.test";
|
||||||
|
|||||||
@@ -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);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user