@dpkit/table
Version:
Data Package implementation in TypeScript.
265 lines • 32.2 kB
JavaScript
import { DataFrame } from "nodejs-polars";
import { describe, expect, it } from "vitest";
import { inspectTable } from "./inspect.js";
describe("inspectTable", () => {
describe("fields validation with fieldsMatch='exact'", () => {
it("should pass when fields exactly match", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
}).lazy();
const schema = {
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should not have fields error when fields same length", async () => {
const table = DataFrame({
id: [1, 2],
age: [30, 25],
}).lazy();
const schema = {
fieldsMatch: "exact",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "number" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([
{
type: "field/name",
fieldName: "name",
actualFieldName: "age",
},
]);
});
});
it("should detect extra fields", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
age: [30, 25],
}).lazy();
const schema = {
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/extra",
fieldNames: ["age"],
});
});
it("should detect missing fields", async () => {
const table = DataFrame({
id: [1, 2],
}).lazy();
const schema = {
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/missing",
fieldNames: ["name"],
});
});
describe("fields validation with fieldsMatch='equal'", () => {
it("should pass when field names match regardless of order", async () => {
const table = DataFrame({
name: ["John", "Jane"],
id: [1, 2],
}).lazy();
const schema = {
fieldsMatch: "equal",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should detect extra fields", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
age: [30, 25],
}).lazy();
const schema = {
fieldsMatch: "equal",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/extra",
fieldNames: ["age"],
});
});
it("should detect missing fields", async () => {
const table = DataFrame({
id: [1, 2],
}).lazy();
const schema = {
fieldsMatch: "equal",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/missing",
fieldNames: ["name"],
});
});
});
describe("fields validation with fieldsMatch='subset'", () => {
it("should pass when data contains all schema fields", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
age: [30, 25],
}).lazy();
const schema = {
fieldsMatch: "subset",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should pass when data contains exact schema fields", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
}).lazy();
const schema = {
fieldsMatch: "subset",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should detect missing fields", async () => {
const table = DataFrame({
id: [1, 2],
}).lazy();
const schema = {
fieldsMatch: "subset",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/missing",
fieldNames: ["name"],
});
});
});
describe("fields validation with fieldsMatch='superset'", () => {
it("should pass when schema contains all data fields", async () => {
const table = DataFrame({
id: [1, 2],
}).lazy();
const schema = {
fieldsMatch: "superset",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should pass when schema contains exact data fields", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
}).lazy();
const schema = {
fieldsMatch: "superset",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should detect extra fields", async () => {
const table = DataFrame({
id: [1, 2],
name: ["John", "Jane"],
age: [30, 25],
}).lazy();
const schema = {
fieldsMatch: "superset",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/extra",
fieldNames: ["age"],
});
});
});
describe("fields validation with fieldsMatch='partial'", () => {
it("should pass when at least one field matches", async () => {
const table = DataFrame({
id: [1, 2],
age: [30, 25],
}).lazy();
const schema = {
fieldsMatch: "partial",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toEqual([]);
});
it("should detect when no fields match", async () => {
const table = DataFrame({
age: [30, 25],
email: ["john@example.com", "jane@example.com"],
}).lazy();
const schema = {
fieldsMatch: "partial",
fields: [
{ name: "id", type: "number" },
{ name: "name", type: "string" },
],
};
const errors = await inspectTable(table, { schema });
expect(errors).toContainEqual({
type: "fields/missing",
fieldNames: ["id", "name"],
});
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5zcGVjdC5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdGFibGUvaW5zcGVjdC5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUE7QUFDekMsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLE1BQU0sUUFBUSxDQUFBO0FBQzdDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxjQUFjLENBQUE7QUFFM0MsUUFBUSxDQUFDLGNBQWMsRUFBRSxHQUFHLEVBQUU7SUFDNUIsUUFBUSxDQUFDLDRDQUE0QyxFQUFFLEdBQUcsRUFBRTtRQUMxRCxFQUFFLENBQUMsdUNBQXVDLEVBQUUsS0FBSyxJQUFJLEVBQUU7WUFDckQsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDO2dCQUN0QixFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUNWLElBQUksRUFBRSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUM7YUFDdkIsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFBO1lBRVQsTUFBTSxNQUFNLEdBQVc7Z0JBQ3JCLE1BQU0sRUFBRTtvQkFDTixFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtvQkFDOUIsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7aUJBQ2pDO2FBQ0YsQ0FBQTtZQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sWUFBWSxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7WUFFcEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtRQUM1QixDQUFDLENBQUMsQ0FBQTtRQUVGLEVBQUUsQ0FBQyxzREFBc0QsRUFBRSxLQUFLLElBQUksRUFBRTtZQUNwRSxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUM7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LEtBQUssSUFBSSxFQUFFO1lBQ2xELE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQztnQkFDdEIsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQztnQkFDYixLQUFLLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSxrQkFBa0IsQ0FBQzthQUNoRCxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7WUFFVCxNQUFNLE1BQU0sR0FBVztnQkFDckIsV0FBVyxFQUFFLFNBQVM7Z0JBQ3RCLE1BQU0sRUFBRTtvQkFDTixFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtvQkFDOUIsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUU7aUJBQ2pDO2FBQ0YsQ0FBQTtZQUVELE1BQU0sTUFBTSxHQUFHLE1BQU0sWUFBWSxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7WUFDcEQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLGNBQWMsQ0FBQztnQkFDNUIsSUFBSSxFQUFFLGdCQUFnQjtnQkFDdEIsVUFBVSxFQUFFLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQzthQUMzQixDQUFDLENBQUE7UUFDSixDQUFDLENBQUMsQ0FBQTtJQUNKLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IFNjaGVtYSB9IGZyb20gXCJAZHBraXQvY29yZVwiXG5pbXBvcnQgeyBEYXRhRnJhbWUgfSBmcm9tIFwibm9kZWpzLXBvbGFyc1wiXG5pbXBvcnQgeyBkZXNjcmliZSwgZXhwZWN0LCBpdCB9IGZyb20gXCJ2aXRlc3RcIlxuaW1wb3J0IHsgaW5zcGVjdFRhYmxlIH0gZnJvbSBcIi4vaW5zcGVjdC50c1wiXG5cbmRlc2NyaWJlKFwiaW5zcGVjdFRhYmxlXCIsICgpID0+IHtcbiAgZGVzY3JpYmUoXCJmaWVsZHMgdmFsaWRhdGlvbiB3aXRoIGZpZWxkc01hdGNoPSdleGFjdCdcIiwgKCkgPT4ge1xuICAgIGl0KFwic2hvdWxkIHBhc3Mgd2hlbiBmaWVsZHMgZXhhY3RseSBtYXRjaFwiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbMSwgMl0sXG4gICAgICAgIG5hbWU6IFtcIkpvaG5cIiwgXCJKYW5lXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0VxdWFsKFtdKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBub3QgaGF2ZSBmaWVsZHMgZXJyb3Igd2hlbiBmaWVsZHMgc2FtZSBsZW5ndGhcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgICBhZ2U6IFszMCwgMjVdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJleGFjdFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXG4gICAgICAgIHtcbiAgICAgICAgICB0eXBlOiBcImZpZWxkL25hbWVcIixcbiAgICAgICAgICBmaWVsZE5hbWU6IFwibmFtZVwiLFxuICAgICAgICAgIGFjdHVhbEZpZWxkTmFtZTogXCJhZ2VcIixcbiAgICAgICAgfSxcbiAgICAgIF0pXG4gICAgfSlcbiAgfSlcblxuICBpdChcInNob3VsZCBkZXRlY3QgZXh0cmEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICBpZDogWzEsIDJdLFxuICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICBhZ2U6IFszMCwgMjVdLFxuICAgIH0pLmxhenkoKVxuXG4gICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICBmaWVsZHM6IFtcbiAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgdHlwZTogXCJmaWVsZHMvZXh0cmFcIixcbiAgICAgIGZpZWxkTmFtZXM6IFtcImFnZVwiXSxcbiAgICB9KVxuICB9KVxuXG4gIGl0KFwic2hvdWxkIGRldGVjdCBtaXNzaW5nIGZpZWxkc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgaWQ6IFsxLCAyXSxcbiAgICB9KS5sYXp5KClcblxuICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgZmllbGRzOiBbXG4gICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgIHR5cGU6IFwiZmllbGRzL21pc3NpbmdcIixcbiAgICAgIGZpZWxkTmFtZXM6IFtcIm5hbWVcIl0sXG4gICAgfSlcbiAgfSlcblxuICBkZXNjcmliZShcImZpZWxkcyB2YWxpZGF0aW9uIHdpdGggZmllbGRzTWF0Y2g9J2VxdWFsJ1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIGZpZWxkIG5hbWVzIG1hdGNoIHJlZ2FyZGxlc3Mgb2Ygb3JkZXJcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBuYW1lOiBbXCJKb2huXCIsIFwiSmFuZVwiXSxcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwiZXF1YWxcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGluc3BlY3RUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvRXF1YWwoW10pXG4gICAgfSlcblxuICAgIGl0KFwic2hvdWxkIGRldGVjdCBleHRyYSBmaWVsZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgICBuYW1lOiBbXCJKb2huXCIsIFwiSmFuZVwiXSxcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwiZXF1YWxcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGluc3BlY3RUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJmaWVsZHMvZXh0cmFcIixcbiAgICAgICAgZmllbGROYW1lczogW1wiYWdlXCJdLFxuICAgICAgfSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgZGV0ZWN0IG1pc3NpbmcgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwiZXF1YWxcIixcbiAgICAgICAgZmllbGRzOiBbXG4gICAgICAgICAgeyBuYW1lOiBcImlkXCIsIHR5cGU6IFwibnVtYmVyXCIgfSxcbiAgICAgICAgICB7IG5hbWU6IFwibmFtZVwiLCB0eXBlOiBcInN0cmluZ1wiIH0sXG4gICAgICAgIF0sXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGluc3BlY3RUYWJsZSh0YWJsZSwgeyBzY2hlbWEgfSlcbiAgICAgIGV4cGVjdChlcnJvcnMpLnRvQ29udGFpbkVxdWFsKHtcbiAgICAgICAgdHlwZTogXCJmaWVsZHMvbWlzc2luZ1wiLFxuICAgICAgICBmaWVsZE5hbWVzOiBbXCJuYW1lXCJdLFxuICAgICAgfSlcbiAgICB9KVxuICB9KVxuXG4gIGRlc2NyaWJlKFwiZmllbGRzIHZhbGlkYXRpb24gd2l0aCBmaWVsZHNNYXRjaD0nc3Vic2V0J1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIGRhdGEgY29udGFpbnMgYWxsIHNjaGVtYSBmaWVsZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgICBuYW1lOiBbXCJKb2huXCIsIFwiSmFuZVwiXSxcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwic3Vic2V0XCIsXG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0VxdWFsKFtdKVxuICAgIH0pXG5cbiAgICBpdChcInNob3VsZCBwYXNzIHdoZW4gZGF0YSBjb250YWlucyBleGFjdCBzY2hlbWEgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgbmFtZTogW1wiSm9oblwiLCBcIkphbmVcIl0sXG4gICAgICB9KS5sYXp5KClcblxuICAgICAgY29uc3Qgc2NoZW1hOiBTY2hlbWEgPSB7XG4gICAgICAgIGZpZWxkc01hdGNoOiBcInN1YnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgZGV0ZWN0IG1pc3NpbmcgZmllbGRzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwic3Vic2V0XCIsXG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL21pc3NpbmdcIixcbiAgICAgICAgZmllbGROYW1lczogW1wibmFtZVwiXSxcbiAgICAgIH0pXG4gICAgfSlcbiAgfSlcblxuICBkZXNjcmliZShcImZpZWxkcyB2YWxpZGF0aW9uIHdpdGggZmllbGRzTWF0Y2g9J3N1cGVyc2V0J1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIHNjaGVtYSBjb250YWlucyBhbGwgZGF0YSBmaWVsZHNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgY29uc3QgdGFibGUgPSBEYXRhRnJhbWUoe1xuICAgICAgICBpZDogWzEsIDJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJzdXBlcnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIHNjaGVtYSBjb250YWlucyBleGFjdCBkYXRhIGZpZWxkc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbMSwgMl0sXG4gICAgICAgIG5hbWU6IFtcIkpvaG5cIiwgXCJKYW5lXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJzdXBlcnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgZGV0ZWN0IGV4dHJhIGZpZWxkc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgICBjb25zdCB0YWJsZSA9IERhdGFGcmFtZSh7XG4gICAgICAgIGlkOiBbMSwgMl0sXG4gICAgICAgIG5hbWU6IFtcIkpvaG5cIiwgXCJKYW5lXCJdLFxuICAgICAgICBhZ2U6IFszMCwgMjVdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJzdXBlcnNldFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9Db250YWluRXF1YWwoe1xuICAgICAgICB0eXBlOiBcImZpZWxkcy9leHRyYVwiLFxuICAgICAgICBmaWVsZE5hbWVzOiBbXCJhZ2VcIl0sXG4gICAgICB9KVxuICAgIH0pXG4gIH0pXG5cbiAgZGVzY3JpYmUoXCJmaWVsZHMgdmFsaWRhdGlvbiB3aXRoIGZpZWxkc01hdGNoPSdwYXJ0aWFsJ1wiLCAoKSA9PiB7XG4gICAgaXQoXCJzaG91bGQgcGFzcyB3aGVuIGF0IGxlYXN0IG9uZSBmaWVsZCBtYXRjaGVzXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgaWQ6IFsxLCAyXSxcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgIH0pLmxhenkoKVxuXG4gICAgICBjb25zdCBzY2hlbWE6IFNjaGVtYSA9IHtcbiAgICAgICAgZmllbGRzTWF0Y2g6IFwicGFydGlhbFwiLFxuICAgICAgICBmaWVsZHM6IFtcbiAgICAgICAgICB7IG5hbWU6IFwiaWRcIiwgdHlwZTogXCJudW1iZXJcIiB9LFxuICAgICAgICAgIHsgbmFtZTogXCJuYW1lXCIsIHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICAgICAgXSxcbiAgICAgIH1cblxuICAgICAgY29uc3QgZXJyb3JzID0gYXdhaXQgaW5zcGVjdFRhYmxlKHRhYmxlLCB7IHNjaGVtYSB9KVxuICAgICAgZXhwZWN0KGVycm9ycykudG9FcXVhbChbXSlcbiAgICB9KVxuXG4gICAgaXQoXCJzaG91bGQgZGV0ZWN0IHdoZW4gbm8gZmllbGRzIG1hdGNoXCIsIGFzeW5jICgpID0+IHtcbiAgICAgIGNvbnN0IHRhYmxlID0gRGF0YUZyYW1lKHtcbiAgICAgICAgYWdlOiBbMzAsIDI1XSxcbiAgICAgICAgZW1haWw6IFtcImpvaG5AZXhhbXBsZS5jb21cIiwgXCJqYW5lQGV4YW1wbGUuY29tXCJdLFxuICAgICAgfSkubGF6eSgpXG5cbiAgICAgIGNvbnN0IHNjaGVtYTogU2NoZW1hID0ge1xuICAgICAgICBmaWVsZHNNYXRjaDogXCJwYXJ0aWFsXCIsXG4gICAgICAgIGZpZWxkczogW1xuICAgICAgICAgIHsgbmFtZTogXCJpZFwiLCB0eXBlOiBcIm51bWJlclwiIH0sXG4gICAgICAgICAgeyBuYW1lOiBcIm5hbWVcIiwgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgICAgICBdLFxuICAgICAgfVxuXG4gICAgICBjb25zdCBlcnJvcnMgPSBhd2FpdCBpbnNwZWN0VGFibGUodGFibGUsIHsgc2NoZW1hIH0pXG4gICAgICBleHBlY3QoZXJyb3JzKS50b0NvbnRhaW5FcXVhbCh7XG4gICAgICAgIHR5cGU6IFwiZmllbGRzL21pc3NpbmdcIixcbiAgICAgICAgZmllbGROYW1lczogW1wiaWRcIiwgXCJuYW1lXCJdLFxuICAgICAgfSlcbiAgICB9KVxuICB9KVxufSlcbiJdfQ==