@dpkit/table
Version:
Data Package implementation in TypeScript.
341 lines • 37.2 kB
JavaScript
import { DataFrame } from "nodejs-polars";
import { describe, expect, it } from "vitest";
import { inspectTable } from "../table/inspect.js";
describe("inspectField", () => {
describe("field name validation", () => {
it("should report an error when field names don't match", async () => {
const table = DataFrame({
actual_id: [1, 2, 3],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "number",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "field/name",
fieldName: "id",
actualFieldName: "actual_id",
});
});
it("should not report errors when field names match", async () => {
const table = DataFrame({
id: [1, 2, 3],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "number",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(0);
});
it("should be case-sensitive when comparing field names", async () => {
const table = DataFrame({
ID: [1, 2, 3],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "number",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(1);
expect(errors).toContainEqual({
type: "field/name",
fieldName: "id",
actualFieldName: "ID",
});
});
});
describe("field type validation", () => {
it("should report an error when field types don't match", async () => {
const table = DataFrame({
id: [true, false, true],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "integer",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(1);
expect(errors).toContainEqual({
type: "field/type",
fieldName: "id",
fieldType: "integer",
actualFieldType: "boolean",
});
});
it("should not report errors when field types match", async () => {
const table = DataFrame({
id: [1, 2, 3],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "number",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(0);
});
});
describe("cell types validation", () => {
it("should inspect string to integer conversion errors", async () => {
const table = DataFrame({
id: ["1", "bad", "3", "4x"],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "integer",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(2);
expect(errors).toContainEqual({
type: "cell/type",
cell: "bad",
fieldName: "id",
rowNumber: 2,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "4x",
fieldName: "id",
rowNumber: 4,
});
});
it("should inspect string to number conversion errors", async () => {
const table = DataFrame({
price: ["10.5", "twenty", "30.75", "$40"],
}).lazy();
const schema = {
fields: [
{
name: "price",
type: "number",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(2);
expect(errors).toContainEqual({
type: "cell/type",
cell: "twenty",
fieldName: "price",
rowNumber: 2,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "$40",
fieldName: "price",
rowNumber: 4,
});
});
it("should inspect string to boolean conversion errors", async () => {
const table = DataFrame({
active: ["true", "yes", "false", "0", "1"],
}).lazy();
const schema = {
fields: [
{
name: "active",
type: "boolean",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(1);
expect(errors).toContainEqual({
type: "cell/type",
cell: "yes",
fieldName: "active",
rowNumber: 2,
});
});
it("should inspect string to date conversion errors", async () => {
const table = DataFrame({
created: ["2023-01-15", "Jan 15, 2023", "20230115", "not-a-date"],
}).lazy();
const schema = {
fields: [
{
name: "created",
type: "date",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(3);
expect(errors).toContainEqual({
type: "cell/type",
cell: "Jan 15, 2023",
fieldName: "created",
rowNumber: 2,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "20230115",
fieldName: "created",
rowNumber: 3,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "not-a-date",
fieldName: "created",
rowNumber: 4,
});
});
it("should inspect string to time conversion errors", async () => {
const table = DataFrame({
time: ["14:30:00", "2:30pm", "invalid", "14h30"],
}).lazy();
const schema = {
fields: [
{
name: "time",
type: "time",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(3);
expect(errors).toContainEqual({
type: "cell/type",
cell: "2:30pm",
fieldName: "time",
rowNumber: 2,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "invalid",
fieldName: "time",
rowNumber: 3,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "14h30",
fieldName: "time",
rowNumber: 4,
});
});
it("should inspect string to year conversion errors", async () => {
const table = DataFrame({
year: ["2023", "23", "MMXXIII", "two-thousand-twenty-three"],
}).lazy();
const schema = {
fields: [
{
name: "year",
type: "year",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(3);
expect(errors).toContainEqual({
type: "cell/type",
cell: "23",
fieldName: "year",
rowNumber: 2,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "MMXXIII",
fieldName: "year",
rowNumber: 3,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "two-thousand-twenty-three",
fieldName: "year",
rowNumber: 4,
});
});
it("should inspect string to datetime conversion errors", async () => {
const table = DataFrame({
timestamp: [
"2023-01-15T14:30:00",
"January 15, 2023 2:30 PM",
"2023-01-15 14:30",
"not-a-datetime",
],
}).lazy();
const schema = {
fields: [
{
name: "timestamp",
type: "datetime",
},
],
};
const errors = await inspectTable(table, { schema });
// Adjust the expectations to match actual behavior
expect(errors.length).toBeGreaterThan(0);
// Check for specific invalid values we expect to fail
expect(errors).toContainEqual({
type: "cell/type",
cell: "January 15, 2023 2:30 PM",
fieldName: "timestamp",
rowNumber: 2,
});
expect(errors).toContainEqual({
type: "cell/type",
cell: "not-a-datetime",
fieldName: "timestamp",
rowNumber: 4,
});
});
it("should pass validation when all cells are valid", async () => {
const table = DataFrame({
id: ["1", "2", "3", "4"],
}).lazy();
const schema = {
fields: [
{
name: "id",
type: "integer",
},
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toHaveLength(0);
});
it("should inspect with non-string source data", async () => {
const table = DataFrame({
is_active: [true, false, true, false],
}).lazy();
const schema = {
fields: [
{
name: "is_active",
type: "boolean",
},
],
};
const errors = await inspectTable(table, { schema });
// Since the column matches the expected type, validation passes
expect(errors).toHaveLength(0);
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zcGVjdC5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vZmllbGQvaW5zcGVjdC5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDekMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBQzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQTtBQUVsRCxRQUFRLENBQUMsY0FBYyxFQUFFLEdBQUcsRUFBRTtJQUM1QixRQUFRLENBQUMsdUJBQXVCLEVBQUUsR0FBRyxFQUFFO1FBQ3JDLEVBQUUsQ0FBQyxxREFBcUQsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNuRSxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUM7Z0JBQ3RCLFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2FBQ3JCLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtZQUVULE1BQU0sTUFBTSxHQUFXO2dCQUNyQixNQUFNLEVBQUU7b0JBQ047d0JBQ0UsSUFBSSxFQUFFLElBQUk7d0JBQ1YsSUFBSSxFQUFFLFFBQVE7cUJBQ2Y7aUJBQ0Y7YUFDRixDQUFBO1lBRUQsTUFBTSxNQUFNLEdBQUcsTUFBTSxZQUFZLENBQUMsS0FBSyxFQUFFLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQTtZQUVwRCxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsY0FBYyxDQUFDO2dCQUM1QixJQUFJLEVBQUUsWUFBWTtnQkFDbEIsU0FBUyxFQUFFLElBQUk7Z0JBQ2YsZUFBZSxFQUFFLFdBQVc7YUFDN0IsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUFDLENBQUE7UUFFRixFQUFFLENBQUMsaURBQWlELEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDL0QsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO2dCQUN0QixFQUFFLEVB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SixDQUFDLENBQUMsQ0FBQSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB0eXBlIHsgU2NoZW1hIH0gZnJvbSBcIkBkcGtpdC9jb3JlXCJcbmltcG9ydCB7IERhdGFGcmFtZSB9IGZyb20gXCJub2RlanMtcG9sYXJzXCJcbmltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGVzdFwiXG5pbXBvcnQgeyBpbnNwZWN0VGFibGUgfSBmcm9tIFwiLi4vdGFibGUvaW5zcGVjdC50c1wiXG5cbmRlc2NyaWJlKFwiaW5zcGVjdEZpZWxkXCIsICgpID0+IHtcbiAgZGVzY3JpYmUoXCJmaWVsZCBuYW1lIHZhbGlkYXRpb25cIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHJlcG9ydCBhbiBlcnJvciB3aGVuIGZpZWxkIG5hbWVzIGRvbid0IG1hdGNoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgYWN0dWFsX2lkOiBbMSwgMiwgM10sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiaWRcIixcbiAgICAgICAgICAgIHR5cGU6IFwibnVtYmVyXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGQvbmFtZVwiLFxuICAgICAgICBmaWVsZE5hbWU6IFwiaWRcIixcbiAgICAgICAgYWN0dWFsRmllbGROYW1lOiBcImFjdHVhbF9pZFwiLFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgbm90IHJlcG9ydCBlcnJvcnMgd2hlbiBmaWVsZCBuYW1lcyBtYXRjaFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbMSwgMiwgM10sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiaWRcIixcbiAgICAgICAgICAgIHR5cGU6IFwibnVtYmVyXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9IYXZlTGVuZ3RoKDApXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIGJlIGNhc2Utc2Vuc2l0aXZlIHdoZW4gY29tcGFyaW5nIGZpZWxkIG5hbWVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgSUQ6IFsxLCAyLCAzXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogXCJpZFwiLFxuICAgICAgICAgICAgdHlwZTogXCJudW1iZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG5cbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgxKVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImZpZWxkL25hbWVcIixcbiAgICAgICAgZmllbGROYW1lOiBcImlkXCIsXG4gICAgICAgIGFjdHVhbEZpZWxkTmFtZTogXCJJRFwiLFxuICAgICAgfSlcbiAgICB9KVxuICB9KVxuXG4gIGRlc2NyaWJlKFwiZmllbGQgdHlwZSB2YWxpZGF0aW9uXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCByZXBvcnQgYW4gZXJyb3Igd2hlbiBmaWVsZCB0eXBlcyBkb24ndCBtYXRjaFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbdHJ1ZSwgZmFsc2UsIHRydWVdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcImlkXCIsXG4gICAgICAgICAgICB0eXBlOiBcImludGVnZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG5cbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgxKVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImZpZWxkL3R5cGVcIixcbiAgICAgICAgZmllbGROYW1lOiBcImlkXCIsXG4gICAgICAgIGZpZWxkVHlwZTogXCJpbnRlZ2VyXCIsXG4gICAgICAgIGFjdHVhbEZpZWxkVHlwZTogXCJib29sZWFuXCIsXG4gICAgICB9KVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBub3QgcmVwb3J0IGVycm9ycyB3aGVuIGZpZWxkIHR5cGVzIG1hdGNoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyLCAzXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogXCJpZFwiLFxuICAgICAgICAgICAgdHlwZTogXCJudW1iZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0hhdmVMZW5ndGgoMClcbiAgICB9KVxuICB9KVxuXG4gIGRlc2NyaWJlKFwiY2VsbCB0eXBlcyB2YWxpZGF0aW9uXCIsICgpID0+IHtcbiAgICBpdChcInNob3VsZCBpbnNwZWN0IHN0cmluZyB0byBpbnRlZ2VyIGNvbnZlcnNpb24gZXJyb3JzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFtcIjFcIiwgXCJiYWRcIiwgXCIzXCIsIFwiNHhcIl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiaWRcIixcbiAgICAgICAgICAgIHR5cGU6IFwiaW50ZWdlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGluc3BlY3RUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcblxuICAgICAgZXhwZWN0KGVycm9ycykudG9IYXZlTGVuZ3RoKDIpXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiY2VsbC90eXBlXCIsXG4gICAgICAgIGNlbGw6IFwiYmFkXCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJpZFwiLFxuICAgICAgICByb3dOdW1iZXI6IDIsXG4gICAgICB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcIjR4XCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJpZFwiLFxuICAgICAgICByb3dOdW1iZXI6IDQsXG4gICAgICB9KVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBpbnNwZWN0IHN0cmluZyB0byBudW1iZXIgY29udmVyc2lvbiBlcnJvcnNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBwcmljZTogW1wiMTAuNVwiLCBcInR3ZW50eVwiLCBcIjMwLjc1XCIsIFwiJDQwXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcInByaWNlXCIsXG4gICAgICAgICAgICB0eXBlOiBcIm51bWJlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGluc3BlY3RUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcblxuICAgICAgZXhwZWN0KGVycm9ycykudG9IYXZlTGVuZ3RoKDIpXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiY2VsbC90eXBlXCIsXG4gICAgICAgIGNlbGw6IFwidHdlbnR5XCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJwcmljZVwiLFxuICAgICAgICByb3dOdW1iZXI6IDIsXG4gICAgICB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcIiQ0MFwiLFxuICAgICAgICBmaWVsZE5hbWU6IFwicHJpY2VcIixcbiAgICAgICAgcm93TnVtYmVyOiA0LFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgaW5zcGVjdCBzdHJpbmcgdG8gYm9vbGVhbiBjb252ZXJzaW9uIGVycm9yc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGFjdGl2ZTogW1widHJ1ZVwiLCBcInllc1wiLCBcImZhbHNlXCIsIFwiMFwiLCBcIjFcIl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiYWN0aXZlXCIsXG4gICAgICAgICAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG5cbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgxKVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcInllc1wiLFxuICAgICAgICBmaWVsZE5hbWU6IFwiYWN0aXZlXCIsXG4gICAgICAgIHJvd051bWJlcjogMixcbiAgICAgIH0pXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIGluc3BlY3Qgc3RyaW5nIHRvIGRhdGUgY29udmVyc2lvbiBlcnJvcnNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBjcmVhdGVkOiBbXCIyMDIzLTAxLTE1XCIsIFwiSmFuIDE1LCAyMDIzXCIsIFwiMjAyMzAxMTVcIiwgXCJub3QtYS1kYXRlXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcImNyZWF0ZWRcIixcbiAgICAgICAgICAgIHR5cGU6IFwiZGF0ZVwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGluc3BlY3RUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcblxuICAgICAgZXhwZWN0KGVycm9ycykudG9IYXZlTGVuZ3RoKDMpXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiY2VsbC90eXBlXCIsXG4gICAgICAgIGNlbGw6IFwiSmFuIDE1LCAyMDIzXCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJjcmVhdGVkXCIsXG4gICAgICAgIHJvd051bWJlcjogMixcbiAgICAgIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiY2VsbC90eXBlXCIsXG4gICAgICAgIGNlbGw6IFwiMjAyMzAxMTVcIixcbiAgICAgICAgZmllbGROYW1lOiBcImNyZWF0ZWRcIixcbiAgICAgICAgcm93TnVtYmVyOiAzLFxuICAgICAgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJjZWxsL3R5cGVcIixcbiAgICAgICAgY2VsbDogXCJub3QtYS1kYXRlXCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJjcmVhdGVkXCIsXG4gICAgICAgIHJvd051bWJlcjogNCxcbiAgICAgIH0pXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIGluc3BlY3Qgc3RyaW5nIHRvIHRpbWUgY29udmVyc2lvbiBlcnJvcnNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICB0aW1lOiBbXCIxNDozMDowMFwiLCBcIjI6MzBwbVwiLCBcImludmFsaWRcIiwgXCIxNGgzMFwiXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogXCJ0aW1lXCIsXG4gICAgICAgICAgICB0eXBlOiBcInRpbWVcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG5cbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgzKVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcIjI6MzBwbVwiLFxuICAgICAgICBmaWVsZE5hbWU6IFwidGltZVwiLFxuICAgICAgICByb3dOdW1iZXI6IDIsXG4gICAgICB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcImludmFsaWRcIixcbiAgICAgICAgZmllbGROYW1lOiBcInRpbWVcIixcbiAgICAgICAgcm93TnVtYmVyOiAzLFxuICAgICAgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJjZWxsL3R5cGVcIixcbiAgICAgICAgY2VsbDogXCIxNGgzMFwiLFxuICAgICAgICBmaWVsZE5hbWU6IFwidGltZVwiLFxuICAgICAgICByb3dOdW1iZXI6IDQsXG4gICAgICB9KVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBpbnNwZWN0IHN0cmluZyB0byB5ZWFyIGNvbnZlcnNpb24gZXJyb3JzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgeWVhcjogW1wiMjAyM1wiLCBcIjIzXCIsIFwiTU1YWElJSVwiLCBcInR3by10aG91c2FuZC10d2VudHktdGhyZWVcIl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwieWVhclwiLFxuICAgICAgICAgICAgdHlwZTogXCJ5ZWFyXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0hhdmVMZW5ndGgoMylcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJjZWxsL3R5cGVcIixcbiAgICAgICAgY2VsbDogXCIyM1wiLFxuICAgICAgICBmaWVsZE5hbWU6IFwieWVhclwiLFxuICAgICAgICByb3dOdW1iZXI6IDIsXG4gICAgICB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcIk1NWFhJSUlcIixcbiAgICAgICAgZmllbGROYW1lOiBcInllYXJcIixcbiAgICAgICAgcm93TnVtYmVyOiAzLFxuICAgICAgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJjZWxsL3R5cGVcIixcbiAgICAgICAgY2VsbDogXCJ0d28tdGhvdXNhbmQtdHdlbnR5LXRocmVlXCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJ5ZWFyXCIsXG4gICAgICAgIHJvd051bWJlcjogNCxcbiAgICAgIH0pXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIGluc3BlY3Qgc3RyaW5nIHRvIGRhdGV0aW1lIGNvbnZlcnNpb24gZXJyb3JzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgdGltZXN0YW1wOiBbXG4gICAgICAgICAgXCIyMDIzLTAxLTE1VDE0OjMwOjAwXCIsXG4gICAgICAgICAgXCJKYW51YXJ5IDE1LCAyMDIzIDI6MzAgUE1cIixcbiAgICAgICAgICBcIjIwMjMtMDEtMTUgMTQ6MzBcIixcbiAgICAgICAgICBcIm5vdC1hLWRhdGV0aW1lXCIsXG4gICAgICAgIF0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwidGltZXN0YW1wXCIsXG4gICAgICAgICAgICB0eXBlOiBcImRhdGV0aW1lXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuXG4gICAgICAvLyBBZGp1c3QgdGhlIGV4cGVjdGF0aW9ucyB0byBtYXRjaCBhY3R1YWwgYmVoYXZpb3JcbiAgICAgIGV4cGVjdChlcnJvcnMubGVuZ3RoKS50b0JlR3JlYXRlclRoYW4oMClcblxuICAgICAgLy8gQ2hlY2sgZm9yIHNwZWNpZmljIGludmFsaWQgdmFsdWVzIHdlIGV4cGVjdCB0byBmYWlsXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiY2VsbC90eXBlXCIsXG4gICAgICAgIGNlbGw6IFwiSmFudWFyeSAxNSwgMjAyMyAyOjMwIFBNXCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJ0aW1lc3RhbXBcIixcbiAgICAgICAgcm93TnVtYmVyOiAyLFxuICAgICAgfSlcblxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImNlbGwvdHlwZVwiLFxuICAgICAgICBjZWxsOiBcIm5vdC1hLWRhdGV0aW1lXCIsXG4gICAgICAgIGZpZWxkTmFtZTogXCJ0aW1lc3RhbXBcIixcbiAgICAgICAgcm93TnVtYmVyOiA0LFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgcGFzcyB2YWxpZGF0aW9uIHdoZW4gYWxsIGNlbGxzIGFyZSB2YWxpZFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbXCIxXCIsIFwiMlwiLCBcIjNcIiwgXCI0XCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcImlkXCIsXG4gICAgICAgICAgICB0eXBlOiBcImludGVnZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG5cbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgwKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBpbnNwZWN0IHdpdGggbm9uLXN0cmluZyBzb3VyY2UgZGF0YVwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlzX2FjdGl2ZTogW3RydWUsIGZhbHNlLCB0cnVlLCBmYWxzZV0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6IFwiaXNfYWN0aXZlXCIsXG4gICAgICAgICAgICB0eXBlOiBcImJvb2xlYW5cIixcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG5cbiAgICAgIC8vIFNpbmNlIHRoZSBjb2x1bW4gbWF0Y2hlcyB0aGUgZXhwZWN0ZWQgdHlwZSwgdmFsaWRhdGlvbiBwYXNzZXNcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvSGF2ZUxlbmd0aCgwKVxuICAgIH0pXG4gIH0pXG59KVxuIl19