UNPKG

@dpkit/table

Version:

Data Package implementation in TypeScript.

341 lines 37.2 kB
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