package com.linkedin.pegasus.generator.test.pdl; import com.linkedin.data.schema.DataSchemaResolver; import com.linkedin.data.schema.NamedDataSchema; import com.linkedin.data.schema.SchemaToPdlEncoder; import com.linkedin.data.schema.resolver.MultiFormatDataSchemaResolver; import java.io.File; import java.io.IOException; import java.io.StringWriter; import org.apache.commons.io.FileUtils; import org.testng.annotations.Test; import static org.testng.Assert.*; public class PdlEncoderTest extends GeneratorTest { private final File pegasusSrcDir = new File(System.getProperty("testDir") + "/pegasus"); private final DataSchemaResolver resolver = MultiFormatDataSchemaResolver.withBuiltinFormats(pegasusSrcDir.getAbsolutePath()); /** * Validate {@link SchemaToPdlEncoder} by parsing a variety of .pdl files, encoding them back to source, and * verifying that the re-encoded source matches the original file. */ @Test public void testEncode() throws IOException { assertRoundTrip("arrays.WithPrimitivesArray"); assertRoundTrip("denormalized.WithNamespacedDeclarations"); assertRoundTrip("denormalized.WithIncludeDeclaration"); assertRoundTrip("deprecated.DeprecatedRecord"); assertRoundTrip("enums.Fruits"); assertRoundTrip("enums.EnumProperties"); assertRoundTrip("enums.DeprecatedSymbols"); assertRoundTrip("escaping.PdlKeywordEscaping"); assertRoundTrip("fixed.Fixed8"); assertRoundTrip("maps.WithPrimitivesMap"); assertRoundTrip("records.Note"); assertRoundTrip("records.WithInclude"); assertRoundTrip("records.WithInlineRecord"); assertRoundTrip("records.WithPrimitives"); assertRoundTrip("records.WithOptionalPrimitives"); assertRoundTrip("records.NumericDefaults"); assertRoundTrip("records.WithComplexTypeDefaults"); assertRoundTrip("typerefs.UnionWithInlineRecord"); assertRoundTrip("typerefs.MapTyperef"); assertRoundTrip("typerefs.IntTyperef"); assertRoundTrip("unions.WithPrimitivesUnion"); } private NamedDataSchema parseSchema(String name) throws IOException { StringBuilder errors = new StringBuilder(); NamedDataSchema dataSchema = resolver.findDataSchema(name, errors); if (errors.length() > 0) { fail("Parse error: " + errors.toString()); } return dataSchema; } private void assertRoundTrip(String relativeName) throws IOException { String fullName = "com.linkedin.pegasus.generator.test.idl." + relativeName; String path = "/" + fullName.replace('.', '/') + ".pdl"; NamedDataSchema parsed = parseSchema(fullName); String original = loadSchema(path); assertNotNull(parsed, "Failed to resolve: " + fullName + "resolver path: " + pegasusSrcDir.getAbsolutePath()); StringWriter writer = new StringWriter(); SchemaToPdlEncoder encoder = new SchemaToPdlEncoder(writer); encoder.setTypeReferenceFormat(SchemaToPdlEncoder.TypeReferenceFormat.PRESERVE); encoder.encode(parsed); String encoded = writer.toString(); assertEqualsIgnoringSpacing(original, encoded); } private void assertEqualsIgnoringSpacing(String lhs, String rhs) { assertEquals(canonicalize(lhs), canonicalize(rhs)); } private String loadSchema(String filename) { try { return FileUtils.readFileToString(new File(pegasusSrcDir, filename)); } catch (IOException e) { fail("Failed to load file: " + filename + ": " + e.getMessage()); return null; } } private String canonicalize(String pdlSource) { return pdlSource .replaceAll("([{}\\[\\]\\?=:])", " $1 ") // force spacing around grammatical symbols .replaceAll(",", " ") // commas are insignificant in pdl, strip them out .replaceAll("\\s+", " ").trim(); // canonicalize spacing } }