@dpkit/ckan
Version:
Fast TypeScript data management framework built on top of the Data Package standard and Polars DataFrames
189 lines • 29.4 kB
JavaScript
import { describe, expect, it } from "vitest";
import ckanPackageFixture from "../fixtures/ckan-package.json" with {
type: "json"
};
import { denormalizeCkanPackage } from "./denormalize.js";
import { normalizeCkanPackage } from "./normalize.js";
describe("denormalizeCkanPackage", () => {
it("denormalizes a Frictionless Data Package to a CKAN package", () => {
// Arrange
const dataPackage = {
name: "test-package",
title: "Test Package",
description: "This is a test package",
version: "1.0.0",
licenses: [
{
name: "cc-by",
title: "Creative Commons Attribution",
path: "http://www.opendefinition.org/licenses/cc-by",
},
],
contributors: [
{
title: "Test Author",
email: "author@example.com",
role: "author",
},
{
title: "Test Maintainer",
email: "maintainer@example.com",
role: "maintainer",
},
],
keywords: ["test", "sample", "data"],
created: "2023-01-01T00:00:00Z",
resources: [
{
name: "test-resource",
path: "https://example.com/data.csv",
format: "csv",
mediatype: "text/csv",
description: "Test resource",
bytes: 1024,
hash: "md5:1234567890abcdef",
},
],
};
// Act
const result = denormalizeCkanPackage(dataPackage);
// Assert
// Basic metadata
expect(result.name).toEqual(dataPackage.name);
expect(result.title).toEqual(dataPackage.title);
expect(result.notes).toEqual(dataPackage.description);
expect(result.version).toEqual(dataPackage.version);
//expect(result.metadata_created).toEqual(dataPackage.created)
// License
if (dataPackage.licenses &&
dataPackage.licenses.length > 0 &&
dataPackage.licenses[0]) {
const license = dataPackage.licenses[0];
if (license.name)
expect(result.license_id).toEqual(license.name);
if (license.title)
expect(result.license_title).toEqual(license.title);
if (license.path)
expect(result.license_url).toEqual(license.path);
}
// Contributors
if (dataPackage.contributors && dataPackage.contributors.length >= 2) {
const author = dataPackage.contributors.find(c => c.role === "author");
const maintainer = dataPackage.contributors.find(c => c.role === "maintainer");
if (author) {
expect(result.author).toEqual(author.title);
expect(result.author_email).toEqual(author.email);
}
if (maintainer) {
expect(result.maintainer).toEqual(maintainer.title);
expect(result.maintainer_email).toEqual(maintainer.email);
}
}
// Tags
if (dataPackage.keywords && dataPackage.keywords.length > 0) {
expect(result.tags).toHaveLength(dataPackage.keywords.length);
dataPackage.keywords.forEach((keyword, index) => {
const tag = result.tags?.[index];
if (tag && keyword) {
expect(tag.name).toEqual(keyword);
expect(tag.display_name).toEqual(keyword);
}
});
}
// Resources
expect(result.resources).toHaveLength(dataPackage.resources.length);
// Verify resources exist
expect(dataPackage.resources.length).toBeGreaterThan(0);
expect(result.resources?.length).toBeGreaterThan(0);
if (dataPackage.resources.length > 0 && result.resources.length > 0) {
// Verify first resource
const firstResource = dataPackage.resources[0];
const firstCkanResource = result.resources[0];
expect(firstCkanResource).toBeDefined();
expect(firstResource).toBeDefined();
if (firstResource && firstCkanResource) {
//expect(firstCkanResource.url).toEqual(firstResource.path)
// Name comes from title or is extracted from path
//const expectedName = firstResource.title || "data.csv" // We know getFilename extracts this from the URL
//expect(firstCkanResource.name).toEqual(expectedName)
expect(firstCkanResource.description).toEqual(firstResource.description);
expect(firstCkanResource.format).toEqual(firstResource.format?.toUpperCase());
expect(firstCkanResource.mimetype).toEqual(firstResource.mediatype);
expect(firstCkanResource.size).toEqual(firstResource.bytes);
expect(firstCkanResource.hash).toEqual(firstResource.hash);
}
}
});
it("handles empty resources array", () => {
// Arrange
const dataPackage = {
name: "test-package",
resources: [],
};
// Act
const result = denormalizeCkanPackage(dataPackage);
// Assert
expect(result.resources).toEqual([]);
});
it("handles undefined optional properties", () => {
// Arrange
const dataPackage = {
resources: [], // Only required property
};
// Act
const result = denormalizeCkanPackage(dataPackage);
// Assert
expect(result.name).toBeUndefined();
expect(result.title).toBeUndefined();
expect(result.notes).toBeUndefined();
expect(result.version).toBeUndefined();
expect(result.metadata_created).toBeUndefined();
expect(result.license_id).toBeUndefined();
expect(result.license_title).toBeUndefined();
expect(result.license_url).toBeUndefined();
expect(result.author).toBeUndefined();
expect(result.author_email).toBeUndefined();
expect(result.maintainer).toBeUndefined();
expect(result.maintainer_email).toBeUndefined();
expect(result.tags).toEqual([]);
expect(result.resources).toEqual([]);
});
it("performs a round-trip conversion (CKAN → DP → CKAN)", () => {
// Arrange
const originalCkanPackage = ckanPackageFixture;
// Act - First normalize to a Frictionless Data Package
const dataPackage = normalizeCkanPackage(originalCkanPackage);
// Then denormalize back to a CKAN package
const resultCkanPackage = denormalizeCkanPackage(dataPackage);
// Assert
// Basic metadata
expect(resultCkanPackage.name).toEqual(originalCkanPackage.name);
expect(resultCkanPackage.title).toEqual(originalCkanPackage.title);
expect(resultCkanPackage.notes).toEqual(originalCkanPackage.notes);
expect(resultCkanPackage.version).toEqual(originalCkanPackage.version);
// License
expect(resultCkanPackage.license_id).toEqual(originalCkanPackage.license_id);
expect(resultCkanPackage.license_title).toEqual(originalCkanPackage.license_title);
expect(resultCkanPackage.license_url).toEqual(originalCkanPackage.license_url);
// Contributors
expect(resultCkanPackage.author).toEqual(originalCkanPackage.author);
expect(resultCkanPackage.author_email).toEqual(originalCkanPackage.author_email);
expect(resultCkanPackage.maintainer).toEqual(originalCkanPackage.maintainer);
expect(resultCkanPackage.maintainer_email).toEqual(originalCkanPackage.maintainer_email);
// Resources - counts might differ due to resource filtering in denormalizeCkanResource
// Some resources might be filtered out if they don't have valid names
expect(resultCkanPackage.resources.length).toBeGreaterThan(0);
// Verify resources are properly converted
//resultCkanPackage.resources.forEach(resource => {
//expect(resource.url).toBeTruthy()
//expect(resource.name).toBeTruthy()
//})
// Tags - verify all tag names are preserved
expect(resultCkanPackage.tags.length).toEqual(originalCkanPackage.tags.length);
originalCkanPackage.tags.forEach(originalTag => {
const matchingTag = resultCkanPackage.tags.find(tag => tag.name === originalTag.name);
expect(matchingTag).toBeTruthy();
});
});
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVub3JtYWxpemUuc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3BhY2thZ2UvcHJvY2Vzcy9kZW5vcm1hbGl6ZS5zcGVjLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUU3QyxPQUFPLGtCQUFrQixNQUFNLCtCQUErQixDQUFDO0lBQzdELElBQUksRUFBRSxNQUFNO0NBQ2IsQ0FBQTtBQUNELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGtCQUFrQixDQUFBO0FBQ3pELE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFBO0FBRXJELFFBQVEsQ0FBQyx3QkFBd0IsRUFBRSxHQUFHLEVBQUU7SUFDdEMsRUFBRSxDQUFDLDREQUE0RCxFQUFFLEdBQUcsRUFBRTtRQUNwRSxVQUFVO1FBQ1YsTUFBTSxXQUFXLEdBQVk7WUFDM0IsSUFBSSxFQUFFLGNBQWM7WUFDcEIsS0FBSyxFQUFFLGNBQWM7WUFDckIsV0FBVyxFQUFFLHdCQUF3QjtZQUNyQyxPQUFPLEVBQUUsT0FBTztZQUNoQixRQUFRLEVBQUU7Z0JBQ1I7b0JBQ0UsSUFBSSxFQUFFLE9BQU87b0JBQ2IsS0FBSyxFQUFFLDhCQUE4QjtvQkFDckMsSUFBSSxFQUFFLDhDQUE4QztpQkFDckQ7YUFDRjtZQUNELFlBQVksRUFBRTtnQkFDWjtvQkFDRSxLQUFLLEVBQUUsYUFBYTtvQkFDcEIsS0FBSyxFQUFFLG9CQUFvQjtvQkFDM0IsSUFBSSxFQUFFLFFBQVE7aUJBQ2Y7Z0JBQ0Q7b0JBQ0UsS0FBSyxFQUFFLGlCQUFpQjtvQkFDeEIsS0FBSyxFQUFFLHdCQUF3QjtvQkFDL0IsSUFBSSxFQUFFLFlBQVk7aUJBQ25CO2FBQ0Y7WUFDRCxRQUFRLEVBQUUsQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQztZQUNwQyxPQUFPLEVBQUUsc0JB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QUFNLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUE7UUFDbEMsQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBQYWNrYWdlIH0gZnJvbSBcIkBkcGtpdC9jb3JlXCJcbmltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGVzdFwiXG5pbXBvcnQgdHlwZSB7IENrYW5QYWNrYWdlIH0gZnJvbSBcIi4uL1BhY2thZ2UuanNcIlxuaW1wb3J0IGNrYW5QYWNrYWdlRml4dHVyZSBmcm9tIFwiLi4vZml4dHVyZXMvY2thbi1wYWNrYWdlLmpzb25cIiB3aXRoIHtcbiAgdHlwZTogXCJqc29uXCIsXG59XG5pbXBvcnQgeyBkZW5vcm1hbGl6ZUNrYW5QYWNrYWdlIH0gZnJvbSBcIi4vZGVub3JtYWxpemUuanNcIlxuaW1wb3J0IHsgbm9ybWFsaXplQ2thblBhY2thZ2UgfSBmcm9tIFwiLi9ub3JtYWxpemUuanNcIlxuXG5kZXNjcmliZShcImRlbm9ybWFsaXplQ2thblBhY2thZ2VcIiwgKCkgPT4ge1xuICBpdChcImRlbm9ybWFsaXplcyBhIEZyaWN0aW9ubGVzcyBEYXRhIFBhY2thZ2UgdG8gYSBDS0FOIHBhY2thZ2VcIiwgKCkgPT4ge1xuICAgIC8vIEFycmFuZ2VcbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICB0aXRsZTogXCJUZXN0IFBhY2thZ2VcIixcbiAgICAgIGRlc2NyaXB0aW9uOiBcIlRoaXMgaXMgYSB0ZXN0IHBhY2thZ2VcIixcbiAgICAgIHZlcnNpb246IFwiMS4wLjBcIixcbiAgICAgIGxpY2Vuc2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcImNjLWJ5XCIsXG4gICAgICAgICAgdGl0bGU6IFwiQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvblwiLFxuICAgICAgICAgIHBhdGg6IFwiaHR0cDovL3d3dy5vcGVuZGVmaW5pdGlvbi5vcmcvbGljZW5zZXMvY2MtYnlcIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBjb250cmlidXRvcnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIHRpdGxlOiBcIlRlc3QgQXV0aG9yXCIsXG4gICAgICAgICAgZW1haWw6IFwiYXV0aG9yQGV4YW1wbGUuY29tXCIsXG4gICAgICAgICAgcm9sZTogXCJhdXRob3JcIixcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIHRpdGxlOiBcIlRlc3QgTWFpbnRhaW5lclwiLFxuICAgICAgICAgIGVtYWlsOiBcIm1haW50YWluZXJAZXhhbXBsZS5jb21cIixcbiAgICAgICAgICByb2xlOiBcIm1haW50YWluZXJcIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICBrZXl3b3JkczogW1widGVzdFwiLCBcInNhbXBsZVwiLCBcImRhdGFcIl0sXG4gICAgICBjcmVhdGVkOiBcIjIwMjMtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICByZXNvdXJjZXM6IFtcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICAgIHBhdGg6IFwiaHR0cHM6Ly9leGFtcGxlLmNvbS9kYXRhLmNzdlwiLFxuICAgICAgICAgIGZvcm1hdDogXCJjc3ZcIixcbiAgICAgICAgICBtZWRpYXR5cGU6IFwidGV4dC9jc3ZcIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogXCJUZXN0IHJlc291cmNlXCIsXG4gICAgICAgICAgYnl0ZXM6IDEwMjQsXG4gICAgICAgICAgaGFzaDogXCJtZDU6MTIzNDU2Nzg5MGFiY2RlZlwiLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9XG5cbiAgICAvLyBBY3RcbiAgICBjb25zdCByZXN1bHQgPSBkZW5vcm1hbGl6ZUNrYW5QYWNrYWdlKGRhdGFQYWNrYWdlKVxuXG4gICAgLy8gQXNzZXJ0XG4gICAgLy8gQmFzaWMgbWV0YWRhdGFcbiAgICBleHBlY3QocmVzdWx0Lm5hbWUpLnRvRXF1YWwoZGF0YVBhY2thZ2UubmFtZSlcbiAgICBleHBlY3QocmVzdWx0LnRpdGxlKS50b0VxdWFsKGRhdGFQYWNrYWdlLnRpdGxlKVxuICAgIGV4cGVjdChyZXN1bHQubm90ZXMpLnRvRXF1YWwoZGF0YVBhY2thZ2UuZGVzY3JpcHRpb24pXG4gICAgZXhwZWN0KHJlc3VsdC52ZXJzaW9uKS50b0VxdWFsKGRhdGFQYWNrYWdlLnZlcnNpb24pXG4gICAgLy9leHBlY3QocmVzdWx0Lm1ldGFkYXRhX2NyZWF0ZWQpLnRvRXF1YWwoZGF0YVBhY2thZ2UuY3JlYXRlZClcblxuICAgIC8vIExpY2Vuc2VcbiAgICBpZiAoXG4gICAgICBkYXRhUGFja2FnZS5saWNlbnNlcyAmJlxuICAgICAgZGF0YVBhY2thZ2UubGljZW5zZXMubGVuZ3RoID4gMCAmJlxuICAgICAgZGF0YVBhY2thZ2UubGljZW5zZXNbMF1cbiAgICApIHtcbiAgICAgIGNvbnN0IGxpY2Vuc2UgPSBkYXRhUGFja2FnZS5saWNlbnNlc1swXVxuICAgICAgaWYgKGxpY2Vuc2UubmFtZSkgZXhwZWN0KHJlc3VsdC5saWNlbnNlX2lkKS50b0VxdWFsKGxpY2Vuc2UubmFtZSlcbiAgICAgIGlmIChsaWNlbnNlLnRpdGxlKSBleHBlY3QocmVzdWx0LmxpY2Vuc2VfdGl0bGUpLnRvRXF1YWwobGljZW5zZS50aXRsZSlcbiAgICAgIGlmIChsaWNlbnNlLnBhdGgpIGV4cGVjdChyZXN1bHQubGljZW5zZV91cmwpLnRvRXF1YWwobGljZW5zZS5wYXRoKVxuICAgIH1cblxuICAgIC8vIENvbnRyaWJ1dG9yc1xuICAgIGlmIChkYXRhUGFja2FnZS5jb250cmlidXRvcnMgJiYgZGF0YVBhY2thZ2UuY29udHJpYnV0b3JzLmxlbmd0aCA+PSAyKSB7XG4gICAgICBjb25zdCBhdXRob3IgPSBkYXRhUGFja2FnZS5jb250cmlidXRvcnMuZmluZChjID0+IGMucm9sZSA9PT0gXCJhdXRob3JcIilcbiAgICAgIGNvbnN0IG1haW50YWluZXIgPSBkYXRhUGFja2FnZS5jb250cmlidXRvcnMuZmluZChcbiAgICAgICAgYyA9PiBjLnJvbGUgPT09IFwibWFpbnRhaW5lclwiLFxuICAgICAgKVxuXG4gICAgICBpZiAoYXV0aG9yKSB7XG4gICAgICAgIGV4cGVjdChyZXN1bHQuYXV0aG9yKS50b0VxdWFsKGF1dGhvci50aXRsZSlcbiAgICAgICAgZXhwZWN0KHJlc3VsdC5hdXRob3JfZW1haWwpLnRvRXF1YWwoYXV0aG9yLmVtYWlsKVxuICAgICAgfVxuXG4gICAgICBpZiAobWFpbnRhaW5lcikge1xuICAgICAgICBleHBlY3QocmVzdWx0Lm1haW50YWluZXIpLnRvRXF1YWwobWFpbnRhaW5lci50aXRsZSlcbiAgICAgICAgZXhwZWN0KHJlc3VsdC5tYWludGFpbmVyX2VtYWlsKS50b0VxdWFsKG1haW50YWluZXIuZW1haWwpXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gVGFnc1xuICAgIGlmIChkYXRhUGFja2FnZS5rZXl3b3JkcyAmJiBkYXRhUGFja2FnZS5rZXl3b3Jkcy5sZW5ndGggPiAwKSB7XG4gICAgICBleHBlY3QocmVzdWx0LnRhZ3MpLnRvSGF2ZUxlbmd0aChkYXRhUGFja2FnZS5rZXl3b3Jkcy5sZW5ndGgpXG4gICAgICBkYXRhUGFja2FnZS5rZXl3b3Jkcy5mb3JFYWNoKChrZXl3b3JkLCBpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB0YWcgPSByZXN1bHQudGFncz8uW2luZGV4XVxuICAgICAgICBpZiAodGFnICYmIGtleXdvcmQpIHtcbiAgICAgICAgICBleHBlY3QodGFnLm5hbWUpLnRvRXF1YWwoa2V5d29yZClcbiAgICAgICAgICBleHBlY3QodGFnLmRpc3BsYXlfbmFtZSkudG9FcXVhbChrZXl3b3JkKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cblxuICAgIC8vIFJlc291cmNlc1xuICAgIGV4cGVjdChyZXN1bHQucmVzb3VyY2VzKS50b0hhdmVMZW5ndGgoZGF0YVBhY2thZ2UucmVzb3VyY2VzLmxlbmd0aClcblxuICAgIC8vIFZlcmlmeSByZXNvdXJjZXMgZXhpc3RcbiAgICBleHBlY3QoZGF0YVBhY2thZ2UucmVzb3VyY2VzLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApXG4gICAgZXhwZWN0KHJlc3VsdC5yZXNvdXJjZXM/Lmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApXG5cbiAgICBpZiAoZGF0YVBhY2thZ2UucmVzb3VyY2VzLmxlbmd0aCA+IDAgJiYgcmVzdWx0LnJlc291cmNlcy5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBWZXJpZnkgZmlyc3QgcmVzb3VyY2VcbiAgICAgIGNvbnN0IGZpcnN0UmVzb3VyY2UgPSBkYXRhUGFja2FnZS5yZXNvdXJjZXNbMF1cbiAgICAgIGNvbnN0IGZpcnN0Q2thblJlc291cmNlID0gcmVzdWx0LnJlc291cmNlc1swXVxuXG4gICAgICBleHBlY3QoZmlyc3RDa2FuUmVzb3VyY2UpLnRvQmVEZWZpbmVkKClcbiAgICAgIGV4cGVjdChmaXJzdFJlc291cmNlKS50b0JlRGVmaW5lZCgpXG5cbiAgICAgIGlmIChmaXJzdFJlc291cmNlICYmIGZpcnN0Q2thblJlc291cmNlKSB7XG4gICAgICAgIC8vZXhwZWN0KGZpcnN0Q2thblJlc291cmNlLnVybCkudG9FcXVhbChmaXJzdFJlc291cmNlLnBhdGgpXG4gICAgICAgIC8vIE5hbWUgY29tZXMgZnJvbSB0aXRsZSBvciBpcyBleHRyYWN0ZWQgZnJvbSBwYXRoXG4gICAgICAgIC8vY29uc3QgZXhwZWN0ZWROYW1lID0gZmlyc3RSZXNvdXJjZS50aXRsZSB8fCBcImRhdGEuY3N2XCIgLy8gV2Uga25vdyBnZXRGaWxlbmFtZSBleHRyYWN0cyB0aGlzIGZyb20gdGhlIFVSTFxuICAgICAgICAvL2V4cGVjdChmaXJzdENrYW5SZXNvdXJjZS5uYW1lKS50b0VxdWFsKGV4cGVjdGVkTmFtZSlcbiAgICAgICAgZXhwZWN0KGZpcnN0Q2thblJlc291cmNlLmRlc2NyaXB0aW9uKS50b0VxdWFsKGZpcnN0UmVzb3VyY2UuZGVzY3JpcHRpb24pXG4gICAgICAgIGV4cGVjdChmaXJzdENrYW5SZXNvdXJjZS5mb3JtYXQpLnRvRXF1YWwoXG4gICAgICAgICAgZmlyc3RSZXNvdXJjZS5mb3JtYXQ/LnRvVXBwZXJDYXNlKCksXG4gICAgICAgIClcbiAgICAgICAgZXhwZWN0KGZpcnN0Q2thblJlc291cmNlLm1pbWV0eXBlKS50b0VxdWFsKGZpcnN0UmVzb3VyY2UubWVkaWF0eXBlKVxuICAgICAgICBleHBlY3QoZmlyc3RDa2FuUmVzb3VyY2Uuc2l6ZSkudG9FcXVhbChmaXJzdFJlc291cmNlLmJ5dGVzKVxuICAgICAgICBleHBlY3QoZmlyc3RDa2FuUmVzb3VyY2UuaGFzaCkudG9FcXVhbChmaXJzdFJlc291cmNlLmhhc2gpXG4gICAgICB9XG4gICAgfVxuICB9KVxuXG4gIGl0KFwiaGFuZGxlcyBlbXB0eSByZXNvdXJjZXMgYXJyYXlcIiwgKCkgPT4ge1xuICAgIC8vIEFycmFuZ2VcbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgICByZXNvdXJjZXM6IFtdLFxuICAgIH1cblxuICAgIC8vIEFjdFxuICAgIGNvbnN0IHJlc3VsdCA9IGRlbm9ybWFsaXplQ2thblBhY2thZ2UoZGF0YVBhY2thZ2UpXG5cbiAgICAvLyBBc3NlcnRcbiAgICBleHBlY3QocmVzdWx0LnJlc291cmNlcykudG9FcXVhbChbXSlcbiAgfSlcblxuICBpdChcImhhbmRsZXMgdW5kZWZpbmVkIG9wdGlvbmFsIHByb3BlcnRpZXNcIiwgKCkgPT4ge1xuICAgIC8vIEFycmFuZ2VcbiAgICBjb25zdCBkYXRhUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIHJlc291cmNlczogW10sIC8vIE9ubHkgcmVxdWlyZWQgcHJvcGVydHlcbiAgICB9XG5cbiAgICAvLyBBY3RcbiAgICBjb25zdCByZXN1bHQgPSBkZW5vcm1hbGl6ZUNrYW5QYWNrYWdlKGRhdGFQYWNrYWdlKVxuXG4gICAgLy8gQXNzZXJ0XG4gICAgZXhwZWN0KHJlc3VsdC5uYW1lKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzdWx0LnRpdGxlKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzdWx0Lm5vdGVzKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzdWx0LnZlcnNpb24pLnRvQmVVbmRlZmluZWQoKVxuICAgIGV4cGVjdChyZXN1bHQubWV0YWRhdGFfY3JlYXRlZCkudG9CZVVuZGVmaW5lZCgpXG4gICAgZXhwZWN0KHJlc3VsdC5saWNlbnNlX2lkKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzdWx0LmxpY2Vuc2VfdGl0bGUpLnRvQmVVbmRlZmluZWQoKVxuICAgIGV4cGVjdChyZXN1bHQubGljZW5zZV91cmwpLnRvQmVVbmRlZmluZWQoKVxuICAgIGV4cGVjdChyZXN1bHQuYXV0aG9yKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzdWx0LmF1dGhvcl9lbWFpbCkudG9CZVVuZGVmaW5lZCgpXG4gICAgZXhwZWN0KHJlc3VsdC5tYWludGFpbmVyKS50b0JlVW5kZWZpbmVkKClcbiAgICBleHBlY3QocmVzdWx0Lm1haW50YWluZXJfZW1haWwpLnRvQmVVbmRlZmluZWQoKVxuICAgIGV4cGVjdChyZXN1bHQudGFncykudG9FcXVhbChbXSlcbiAgICBleHBlY3QocmVzdWx0LnJlc291cmNlcykudG9FcXVhbChbXSlcbiAgfSlcblxuICBpdChcInBlcmZvcm1zIGEgcm91bmQtdHJpcCBjb252ZXJzaW9uIChDS0FOIOKGkiBEUCDihpIgQ0tBTilcIiwgKCkgPT4ge1xuICAgIC8vIEFycmFuZ2VcbiAgICBjb25zdCBvcmlnaW5hbENrYW5QYWNrYWdlID0gY2thblBhY2thZ2VGaXh0dXJlIGFzIENrYW5QYWNrYWdlXG5cbiAgICAvLyBBY3QgLSBGaXJzdCBub3JtYWxpemUgdG8gYSBGcmljdGlvbmxlc3MgRGF0YSBQYWNrYWdlXG4gICAgY29uc3QgZGF0YVBhY2thZ2UgPSBub3JtYWxpemVDa2FuUGFja2FnZShvcmlnaW5hbENrYW5QYWNrYWdlKVxuXG4gICAgLy8gVGhlbiBkZW5vcm1hbGl6ZSBiYWNrIHRvIGEgQ0tBTiBwYWNrYWdlXG4gICAgY29uc3QgcmVzdWx0Q2thblBhY2thZ2UgPSBkZW5vcm1hbGl6ZUNrYW5QYWNrYWdlKGRhdGFQYWNrYWdlKVxuXG4gICAgLy8gQXNzZXJ0XG4gICAgLy8gQmFzaWMgbWV0YWRhdGFcbiAgICBleHBlY3QocmVzdWx0Q2thblBhY2thZ2UubmFtZSkudG9FcXVhbChvcmlnaW5hbENrYW5QYWNrYWdlLm5hbWUpXG4gICAgZXhwZWN0KHJlc3VsdENrYW5QYWNrYWdlLnRpdGxlKS50b0VxdWFsKG9yaWdpbmFsQ2thblBhY2thZ2UudGl0bGUpXG4gICAgZXhwZWN0KHJlc3VsdENrYW5QYWNrYWdlLm5vdGVzKS50b0VxdWFsKG9yaWdpbmFsQ2thblBhY2thZ2Uubm90ZXMpXG4gICAgZXhwZWN0KHJlc3VsdENrYW5QYWNrYWdlLnZlcnNpb24pLnRvRXF1YWwob3JpZ2luYWxDa2FuUGFja2FnZS52ZXJzaW9uKVxuXG4gICAgLy8gTGljZW5zZVxuICAgIGV4cGVjdChyZXN1bHRDa2FuUGFja2FnZS5saWNlbnNlX2lkKS50b0VxdWFsKG9yaWdpbmFsQ2thblBhY2thZ2UubGljZW5zZV9pZClcbiAgICBleHBlY3QocmVzdWx0Q2thblBhY2thZ2UubGljZW5zZV90aXRsZSkudG9FcXVhbChcbiAgICAgIG9yaWdpbmFsQ2thblBhY2thZ2UubGljZW5zZV90aXRsZSxcbiAgICApXG4gICAgZXhwZWN0KHJlc3VsdENrYW5QYWNrYWdlLmxpY2Vuc2VfdXJsKS50b0VxdWFsKFxuICAgICAgb3JpZ2luYWxDa2FuUGFja2FnZS5saWNlbnNlX3VybCxcbiAgICApXG5cbiAgICAvLyBDb250cmlidXRvcnNcbiAgICBleHBlY3QocmVzdWx0Q2thblBhY2thZ2UuYXV0aG9yKS50b0VxdWFsKG9yaWdpbmFsQ2thblBhY2thZ2UuYXV0aG9yKVxuICAgIGV4cGVjdChyZXN1bHRDa2FuUGFja2FnZS5hdXRob3JfZW1haWwpLnRvRXF1YWwoXG4gICAgICBvcmlnaW5hbENrYW5QYWNrYWdlLmF1dGhvcl9lbWFpbCxcbiAgICApXG4gICAgZXhwZWN0KHJlc3VsdENrYW5QYWNrYWdlLm1haW50YWluZXIpLnRvRXF1YWwob3JpZ2luYWxDa2FuUGFja2FnZS5tYWludGFpbmVyKVxuICAgIGV4cGVjdChyZXN1bHRDa2FuUGFja2FnZS5tYWludGFpbmVyX2VtYWlsKS50b0VxdWFsKFxuICAgICAgb3JpZ2luYWxDa2FuUGFja2FnZS5tYWludGFpbmVyX2VtYWlsLFxuICAgIClcblxuICAgIC8vIFJlc291cmNlcyAtIGNvdW50cyBtaWdodCBkaWZmZXIgZHVlIHRvIHJlc291cmNlIGZpbHRlcmluZyBpbiBkZW5vcm1hbGl6ZUNrYW5SZXNvdXJjZVxuICAgIC8vIFNvbWUgcmVzb3VyY2VzIG1pZ2h0IGJlIGZpbHRlcmVkIG91dCBpZiB0aGV5IGRvbid0IGhhdmUgdmFsaWQgbmFtZXNcbiAgICBleHBlY3QocmVzdWx0Q2thblBhY2thZ2UucmVzb3VyY2VzLmxlbmd0aCkudG9CZUdyZWF0ZXJUaGFuKDApXG4gICAgLy8gVmVyaWZ5IHJlc291cmNlcyBhcmUgcHJvcGVybHkgY29udmVydGVkXG4gICAgLy9yZXN1bHRDa2FuUGFja2FnZS5yZXNvdXJjZXMuZm9yRWFjaChyZXNvdXJjZSA9PiB7XG4gICAgLy9leHBlY3QocmVzb3VyY2UudXJsKS50b0JlVHJ1dGh5KClcbiAgICAvL2V4cGVjdChyZXNvdXJjZS5uYW1lKS50b0JlVHJ1dGh5KClcbiAgICAvL30pXG5cbiAgICAvLyBUYWdzIC0gdmVyaWZ5IGFsbCB0YWcgbmFtZXMgYXJlIHByZXNlcnZlZFxuICAgIGV4cGVjdChyZXN1bHRDa2FuUGFja2FnZS50YWdzLmxlbmd0aCkudG9FcXVhbChcbiAgICAgIG9yaWdpbmFsQ2thblBhY2thZ2UudGFncy5sZW5ndGgsXG4gICAgKVxuICAgIG9yaWdpbmFsQ2thblBhY2thZ2UudGFncy5mb3JFYWNoKG9yaWdpbmFsVGFnID0+IHtcbiAgICAgIGNvbnN0IG1hdGNoaW5nVGFnID0gcmVzdWx0Q2thblBhY2thZ2UudGFncy5maW5kKFxuICAgICAgICB0YWcgPT4gdGFnLm5hbWUgPT09IG9yaWdpbmFsVGFnLm5hbWUsXG4gICAgICApXG4gICAgICBleHBlY3QobWF0Y2hpbmdUYWcpLnRvQmVUcnV0aHkoKVxuICAgIH0pXG4gIH0pXG59KVxuIl19