diff options
author | gjoranv <gjoranv@gmail.com> | 2017-08-17 13:48:18 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-17 13:48:18 +0200 |
commit | 52f25f90f06fc5adce9f8f3f092f7d2c3a78c289 (patch) | |
tree | dc0071c314bee0d66fb96db73df3e6185c7cece1 | |
parent | 6b2caed697a92f6d7ddd96e363ae7f6dbfdf9639 (diff) | |
parent | 81af3fc3a4c50b72ef45c310efbfc4f915e263e1 (diff) |
Merge pull request #3133 from vespa-engine/gjoranv/config-def-package
Gjoranv/config def package
25 files changed, 306 insertions, 417 deletions
diff --git a/config-class-plugin/src/main/java/com/yahoo/vespa/ConfigGenMojo.java b/config-class-plugin/src/main/java/com/yahoo/vespa/ConfigGenMojo.java index 66c62b3b194..64941fdc1a2 100644 --- a/config-class-plugin/src/main/java/com/yahoo/vespa/ConfigGenMojo.java +++ b/config-class-plugin/src/main/java/com/yahoo/vespa/ConfigGenMojo.java @@ -1,6 +1,7 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.vespa; +import com.yahoo.config.codegen.DefParser; import com.yahoo.config.codegen.MakeConfig; import com.yahoo.config.codegen.MakeConfigProperties; import com.yahoo.config.codegen.PropertyException; @@ -19,6 +20,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static com.yahoo.config.codegen.DefParser.DEFAULT_PACKAGE_PREFIX; + /** * Goal which generates config classes from def-files. @@ -58,7 +61,7 @@ public class ConfigGenMojo extends AbstractMojo { /** * Package prefix of generated configs. The resulting package name will be packagePrefix.namespace if specified. */ - @Parameter(property = "plugin.configuration.packagePrefix", defaultValue = "com.yahoo.") + @Parameter(property = "plugin.configuration.packagePrefix", defaultValue = DEFAULT_PACKAGE_PREFIX) private String packagePrefix; /** diff --git a/config-lib/src/test/java/com/yahoo/config/codegen/NamespaceAndPackageTest.java b/config-lib/src/test/java/com/yahoo/config/codegen/NamespaceAndPackageTest.java new file mode 100644 index 00000000000..904d1fc049a --- /dev/null +++ b/config-lib/src/test/java/com/yahoo/config/codegen/NamespaceAndPackageTest.java @@ -0,0 +1,33 @@ +package com.yahoo.config.codegen; + +import com.github.myproject.NamespaceAndPackageConfig; +import com.github.myproject.PackageConfig; +import com.yahoo.my.namespace.NamespaceConfig; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +/** + * @author gjoranv + */ +public class NamespaceAndPackageTest { + private static String NAMESPACE = "my.namespace"; + private static String PACKAGE = "com.github.myproject"; + + @Test + public void namespace_is_set_from_def_file() { + assertThat(NamespaceConfig.CONFIG_DEF_NAMESPACE, is(NAMESPACE)); + } + + @Test + public void package_is_used_as_namespace_when_namespace_is_not_set_explicitly() { + assertThat(PackageConfig.CONFIG_DEF_NAMESPACE, is(PACKAGE)); + } + + @Test + public void package_does_not_override_namespace() { + assertThat(NamespaceAndPackageConfig.CONFIG_DEF_NAMESPACE, is(NAMESPACE)); + + } +} diff --git a/config-lib/src/test/resources/configdefinitions/arraytypes.def b/config-lib/src/test/resources/configdefinitions/arraytypes.def deleted file mode 100644 index 8add790c6cb..00000000000 --- a/config-lib/src/test/resources/configdefinitions/arraytypes.def +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -# Config containing only simple array types that can be used for testing -# individual types in detail. -namespace=test - -boolarr[] bool -doublearr[] double -enumarr[] enum { VAL1, VAL2 } -intarr[] int -longarr[] long -stringarr[] string diff --git a/config-lib/src/test/resources/configdefinitions/chains-test.def b/config-lib/src/test/resources/configdefinitions/chains-test.def deleted file mode 100644 index 88921b96d8d..00000000000 --- a/config-lib/src/test/resources/configdefinitions/chains-test.def +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -# Chains configuration -namespace=test - -component[].id string - -# Configured functionality provided by this - comes in addition to those set in the code -component[].dependencies.provides[] string - -# Configured "before" dependencies provided by this - comes in addition to those set in the code -component[].dependencies.before[] string - -# Configured "after" dependencies provided by this - comes in addition to those set in the code -component[].dependencies.after[] string - -# The id of this chain. The id has the form name(:version)? -# where the version has the form 1(.2(.3(.identifier)?)?)?. -# The default chain must be called "default". -chain[].id string - -#The type of this chain -chain[].type enum {DOCPROC, SEARCH} default=SEARCH - -# The id of a component to include in this chain. -# The id has the form fullclassname(:version)? -# where the version has the form 1(.2(.3(.identifier)?)?)?. -chain[].component[] string - -# The optional list of chain ids this inherits. -# The ids has the form name(:version)? -# where the version has the form 1(.2(.3(.identifier)?)?)?. -# If the version is not specified the newest version is used. -chain[].inherit[] string - -# The optional list of component ids to exclude from this chain even if they exists in inherited chains -# If versions are specified in these ids, they are ignored. -chain[].exclude[] string - -# The phases for a chain -chain[].phase[].id string -chain[].phase[].before[] string -chain[].phase[].after[] string diff --git a/config-lib/src/test/resources/configdefinitions/datastructures.def b/config-lib/src/test/resources/configdefinitions/datastructures.def deleted file mode 100644 index 7b0aa22c941..00000000000 --- a/config-lib/src/test/resources/configdefinitions/datastructures.def +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test - -date[] string - -stock[].ticker string -stock[].type enum { COMMON, ETF, ETC } default=COMMON -stock[].volume[] int - -basicstruct.foo string default="foo" -basicstruct.bar int default=0 diff --git a/config-lib/src/test/resources/configdefinitions/defaulttest.def b/config-lib/src/test/resources/configdefinitions/defaulttest.def deleted file mode 100644 index d1210890184..00000000000 --- a/config-lib/src/test/resources/configdefinitions/defaulttest.def +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test - -nondefaultstring string -defaultstring string default="thedefault" - -nondefaultreference reference -defaultreference reference default="thedefault" diff --git a/config-lib/src/test/resources/configdefinitions/md5test.def b/config-lib/src/test/resources/configdefinitions/md5test.def deleted file mode 100644 index b419bd975bb..00000000000 --- a/config-lib/src/test/resources/configdefinitions/md5test.def +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -# version=4 , version in comment does not count. - -# Added empty line to see if we can confuse -# the server's md5 calculation -namespace=test - -#even adding a variable name starting with 'version' -versiontag int default=3 - -blabla string default="" -tabs string default=" " -test int - -# test multiple spaces/tabs -spaces int -singletab string -multitabs double - -# test enum -normal enum { VAL1, VAL2 } default=VAL1 -spacevalues enum { V1 , V2 , V3 , V4 } default=V3 - -# Comments and empty lines at the end diff --git a/config-lib/src/test/resources/configdefinitions/string.def b/config-lib/src/test/resources/configdefinitions/namespace-and-package.def index 63d189c3a4e..4e61d25f05f 100755..100644 --- a/config-lib/src/test/resources/configdefinitions/string.def +++ b/config-lib/src/test/resources/configdefinitions/namespace-and-package.def @@ -1,4 +1,7 @@ # Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test -stringVal string default="_default_" +namespace=my.namespace + +package=com.github.myproject + +a int diff --git a/config-lib/src/test/resources/configdefinitions/namespace.def b/config-lib/src/test/resources/configdefinitions/namespace.def index d92dc656fe7..b1406fc1bc4 100644 --- a/config-lib/src/test/resources/configdefinitions/namespace.def +++ b/config-lib/src/test/resources/configdefinitions/namespace.def @@ -1,6 +1,5 @@ # Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test -namespace=myproject.config +namespace=my.namespace a int diff --git a/config-lib/src/test/resources/configdefinitions/specialtypes.def b/config-lib/src/test/resources/configdefinitions/package.def index 3b129c810c0..eba915738a5 100644 --- a/config-lib/src/test/resources/configdefinitions/specialtypes.def +++ b/config-lib/src/test/resources/configdefinitions/package.def @@ -1,5 +1,5 @@ # Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test -myfile file -myref reference +package=com.github.myproject + +a int diff --git a/config-lib/src/test/resources/configdefinitions/simpletypes.def b/config-lib/src/test/resources/configdefinitions/simpletypes.def deleted file mode 100644 index b54ea43435d..00000000000 --- a/config-lib/src/test/resources/configdefinitions/simpletypes.def +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -# Config containing only simple leaf types with default values, that can be used -# for testing individual types in detail. -namespace=test - -boolval bool default=false -doubleval double default=0.0 -enumval enum { VAL1, VAL2 } default=VAL1 -intval int default=0 -longval long default=0 -stringval string default="s" diff --git a/config-lib/src/test/resources/configdefinitions/standard.def b/config-lib/src/test/resources/configdefinitions/standard.def deleted file mode 100644 index 36c4c55f339..00000000000 --- a/config-lib/src/test/resources/configdefinitions/standard.def +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -# Config containing only simple leaf types with default values, that can be used -# for testing individual types in detail. -namespace=test - -basicStruct.intVal int default=0 -basicStruct.stringVal string default="s" -stringArr[] string diff --git a/config-lib/src/test/resources/configdefinitions/structtypes.def b/config-lib/src/test/resources/configdefinitions/structtypes.def deleted file mode 100644 index 5a646efc2c7..00000000000 --- a/config-lib/src/test/resources/configdefinitions/structtypes.def +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -# Config containing only structs in various forms -namespace=test - -simple.name string default="_default_" -simple.gender enum { MALE, FEMALE } default=MALE -simple.emails[] string - -nested.inner.name string default="_default_" -nested.inner.gender enum { MALE, FEMALE } default=MALE -nested.inner.emails[] string - -simplearr[].name string -simplearr[].gender enum { MALE, FEMALE } - -nestedarr[].inner.name string -nestedarr[].inner.gender enum { MALE, FEMALE } -nestedarr[].inner.emails[] string - -complexarr[].innerarr[].name string -complexarr[].innerarr[].gender enum { MALE, FEMALE } diff --git a/config-lib/src/test/resources/configdefinitions/test-nodefs.def b/config-lib/src/test/resources/configdefinitions/test-nodefs.def deleted file mode 100644 index b4c46a89695..00000000000 --- a/config-lib/src/test/resources/configdefinitions/test-nodefs.def +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test - -# test config vars with no defaults - -s string -j int -b bool -f double -e enum { AA, BB, CC } - -basicstruct.foo string -basicstruct.bar int - -arr[].s string -arr[].i int diff --git a/config-lib/src/test/resources/configdefinitions/test-nonstring.def b/config-lib/src/test/resources/configdefinitions/test-nonstring.def deleted file mode 100644 index 474c11770f1..00000000000 --- a/config-lib/src/test/resources/configdefinitions/test-nonstring.def +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test - -# Test non-string config vars with defaults - -i int default=0 -b bool default=false -d double default=0.0 -e enum { AA, BB, CC } default=AA diff --git a/config-lib/src/test/resources/configdefinitions/test-reference.def b/config-lib/src/test/resources/configdefinitions/test-reference.def deleted file mode 100644 index b5d82a7b4b6..00000000000 --- a/config-lib/src/test/resources/configdefinitions/test-reference.def +++ /dev/null @@ -1,4 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test - -configId reference default=":parent:" diff --git a/config-lib/src/test/resources/configdefinitions/testnamespace.def b/config-lib/src/test/resources/configdefinitions/testnamespace.def deleted file mode 100644 index 6e58c691097..00000000000 --- a/config-lib/src/test/resources/configdefinitions/testnamespace.def +++ /dev/null @@ -1,3 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=foo -basicStruct.stringVal string diff --git a/config-lib/src/test/resources/configdefinitions/unicode.def b/config-lib/src/test/resources/configdefinitions/unicode.def deleted file mode 100644 index 9a1ab170d92..00000000000 --- a/config-lib/src/test/resources/configdefinitions/unicode.def +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -namespace=test - -unicodestring1 string -unicodestring2 string default="abc æøå 囲碁 ÆØÅ ABC" diff --git a/configgen/src/main/java/com/yahoo/config/codegen/CNode.java b/configgen/src/main/java/com/yahoo/config/codegen/CNode.java index 260d70ad0e6..9dc7923b71b 100644 --- a/configgen/src/main/java/com/yahoo/config/codegen/CNode.java +++ b/configgen/src/main/java/com/yahoo/config/codegen/CNode.java @@ -3,10 +3,12 @@ package com.yahoo.config.codegen; import java.util.StringTokenizer; +import static com.yahoo.config.codegen.DefParser.DEFAULT_PACKAGE_PREFIX; + /** * Abstract superclass for all nodes representing a definition file. * - * @author <a href="gv@yahoo-inc.com">G. Voldengen</a> + * @author gjoranv */ public abstract class CNode { @@ -20,8 +22,10 @@ public abstract class CNode { // TODO: remove! Only set for the root node, and root.getName() returns the same thing! String defName = null; + String defVersion = ""; String defNamespace = null; + String defPackage = null; String defMd5 = "MISSING MD5"; String comment = ""; @@ -78,13 +82,21 @@ public abstract class CNode { } public String getNamespace() { - return defNamespace; + if (defNamespace != null) return defNamespace; + if (defPackage != null) return defPackage; + return null; } void setNamespace(String namespace) { defNamespace = namespace; } + public String getPackage() { + return defPackage; + } + + void setPackage(String defPackage) { this.defPackage = defPackage; } + public String getComment() { return comment; } @@ -155,7 +167,11 @@ public abstract class CNode { @Override public String toString() { - return getNamespace()+"."+getName()+","+getVersion(); + return "CNode{" + + "namespace='" + defNamespace + '\'' + + ", package='" + defPackage + '\'' + + ", name='" + name + '\'' + + ", version='" + defVersion + '\'' + + '}'; } - } diff --git a/configgen/src/main/java/com/yahoo/config/codegen/DefParser.java b/configgen/src/main/java/com/yahoo/config/codegen/DefParser.java index 54b882d276c..09a751bdde7 100644 --- a/configgen/src/main/java/com/yahoo/config/codegen/DefParser.java +++ b/configgen/src/main/java/com/yahoo/config/codegen/DefParser.java @@ -14,10 +14,17 @@ import java.util.regex.Pattern; * @author hmusum */ public class DefParser { + public static final String DEFAULT_PACKAGE_PREFIX = "com.yahoo."; + static final Pattern commentPattern = Pattern.compile("^\\s*#+\\s*(.*?)\\s*$"); public static final Pattern versionPattern = Pattern.compile("^(version\\s*=\\s*)([0-9][0-9-]*)$"); - // Namespace must start with a letter, since Java (Java language Spec, section 3.8) and C++ identifiers cannot start with a digit - public static final Pattern namespacePattern = Pattern.compile("^(namespace\\s*=\\s*)(([a-z][a-z0-9_]*)+([.][a-z][a-z0-9_]*)*)$"); + // Namespace/package must start with a letter, since Java (Java language Spec, section 3.8) and C++ identifiers cannot start with a digit + public static final Pattern namespacePattern = getNamespacePattern("namespace"); + public static final Pattern packagePattern = getNamespacePattern("package"); + + private static Pattern getNamespacePattern(String directive) { + return Pattern.compile("^(" + directive + "\\s*=\\s*)(([a-z][a-z0-9_]*)+([.][a-z][a-z0-9_]*)*)$"); + } private final BufferedReader reader; private final String name; @@ -127,6 +134,12 @@ public class DefParser { nd.addNormalizedLine(line); return; } + Matcher packageMatcher = packagePattern.matcher(line); + if (packageMatcher.matches()) { + parsePackageLine(packageMatcher.group(2)); + nd.addNormalizedLine(line); + return; + } // Only add lines that are not version, namespace or comment lines nd.addNormalizedLine(line); DefLine defLine = new DefLine(line); @@ -148,14 +161,19 @@ public class DefParser { } private void parseNamespaceLine(String namespace) { - if (namespace.startsWith("com.yahoo.")) - throw new IllegalArgumentException("Remove 'com.yahoo.' from the namespace '" + namespace + - "' - it will be automatically added to the java package name."); + if (namespace.startsWith(DEFAULT_PACKAGE_PREFIX)) + throw new IllegalArgumentException("Please use 'package' instead of 'namespace'."); root.setNamespace(namespace); root.setComment(comment); comment = ""; } + private void parsePackageLine(String defPackage) { + root.setPackage(defPackage); + root.setComment(comment); + comment = ""; + } + void parseLines(CNode root, List<String> defLines, NormalizedDefinition nd) throws DefParserException { DefParserException failure = null; int lineNumber = 1; diff --git a/configgen/src/main/java/com/yahoo/config/codegen/MakeConfig.java b/configgen/src/main/java/com/yahoo/config/codegen/MakeConfig.java index 91d401c91b7..ef9af1c2b11 100644 --- a/configgen/src/main/java/com/yahoo/config/codegen/MakeConfig.java +++ b/configgen/src/main/java/com/yahoo/config/codegen/MakeConfig.java @@ -18,11 +18,11 @@ public class MakeConfig { classBuilder = createClassBuilder(root, nd, properties); } - public static ClassBuilder createClassBuilder(InnerCNode root, NormalizedDefinition nd, MakeConfigProperties prop) { - if (prop.language.equals("cppng") || prop.language.equals("cpp")) - return new CppClassBuilder(root, nd, prop.destDir, prop.dirInRoot); + public static ClassBuilder createClassBuilder(InnerCNode root, NormalizedDefinition nd, MakeConfigProperties properties) { + if (isCpp(properties)) + return new CppClassBuilder(root, nd, properties.destDir, properties.dirInRoot); else - return new JavaClassBuilder(root, nd, prop.destDir, prop.javaPackagePrefix); + return new JavaClassBuilder(root, nd, properties.destDir, properties.javaPackagePrefix); } public static boolean makeConfig(MakeConfigProperties properties) throws FileNotFoundException { @@ -31,7 +31,7 @@ public class MakeConfig { if (name.endsWith(".def")) name = name.substring(0, name.length() - 4); DefParser parser = new DefParser(name, new FileReader(specFile)); InnerCNode configRoot = parser.getTree(); - checkNamespace(name, configRoot); + checkNamespaceAndPacakge(name, configRoot, isCpp(properties)); if (configRoot != null) { MakeConfig mc = new MakeConfig(configRoot, parser.getNormalizedDefinition(), properties); mc.buildClasses(); @@ -73,9 +73,15 @@ public class MakeConfig { } } - private static void checkNamespace(String name, InnerCNode configRoot) { - if (configRoot.defNamespace == null) + private static void checkNamespaceAndPacakge(String name, InnerCNode configRoot, boolean isCpp) { + if (isCpp && configRoot.defNamespace == null) throw new IllegalArgumentException("In config definition '" + name + "': A namespace is required"); + if (configRoot.defNamespace == null && configRoot.defPackage == null) + throw new IllegalArgumentException("In config definition '" + name + "': A package (or namespace) is required"); + } + + private static boolean isCpp(MakeConfigProperties properties) { + return (properties.language.equals("cppng") || properties.language.equals("cpp")); } // The Exceptions class below is copied from vespajlib/com.yahoo.protect.Exceptions diff --git a/configgen/src/main/scala/com/yahoo/config/codegen/JavaClassBuilder.scala b/configgen/src/main/scala/com/yahoo/config/codegen/JavaClassBuilder.scala index 578a8215750..518815d5a10 100644 --- a/configgen/src/main/scala/com/yahoo/config/codegen/JavaClassBuilder.scala +++ b/configgen/src/main/scala/com/yahoo/config/codegen/JavaClassBuilder.scala @@ -4,6 +4,7 @@ package com.yahoo.config.codegen import java.io.{File, FileNotFoundException, FileOutputStream, PrintStream} import com.yahoo.config.codegen.ConfigGenerator.{createClassName, indentCode} +import com.yahoo.config.codegen.DefParser.DEFAULT_PACKAGE_PREFIX import scala.collection.JavaConverters._ import scala.util.Random @@ -22,13 +23,13 @@ class JavaClassBuilder( { import JavaClassBuilder._ - val packagePrefix = if (rawPackagePrefix != null) rawPackagePrefix else "com.yahoo." - val javaPackage = packagePrefix + root.getNamespace + val packagePrefix = if (rawPackagePrefix != null) rawPackagePrefix else DEFAULT_PACKAGE_PREFIX + val javaPackage = if (root.getPackage != null) root.getPackage else packagePrefix + root.getNamespace val className = createClassName(root.getName) override def createConfigClasses() { try { - val outFile = new File(getDestPath(destDir, root.getNamespace), className + ".java") + val outFile = new File(getDestPath(destDir, javaPackage), className + ".java") var out: PrintStream = null try { out = new PrintStream(new FileOutputStream(outFile)) @@ -126,12 +127,12 @@ class JavaClassBuilder( /** * @param rootDir The root directory for the destination path. - * @param namespace The namespace from the def file + * @param javaPackage The java package * @return the destination path for the generated config file, including the given rootDir. */ - private def getDestPath(rootDir: File, namespace: String): File = { + private def getDestPath(rootDir: File, javaPackage: String): File = { var dir: File = rootDir - val subDirs: Array[String] = (packagePrefix + namespace).split("""\.""") + val subDirs: Array[String] = javaPackage.split("""\.""") for (subDir <- subDirs) { dir = new File(dir, subDir) this.synchronized { diff --git a/configgen/src/test/java/com/yahoo/config/codegen/DefParserNamespaceTest.java b/configgen/src/test/java/com/yahoo/config/codegen/DefParserNamespaceTest.java index a0dff8dcf91..049ed3fe753 100644 --- a/configgen/src/test/java/com/yahoo/config/codegen/DefParserNamespaceTest.java +++ b/configgen/src/test/java/com/yahoo/config/codegen/DefParserNamespaceTest.java @@ -4,13 +4,12 @@ import org.junit.Test; import java.io.IOException; -import static com.yahoo.config.codegen.DefParserTest.assertExceptionAndMessage; +import static com.yahoo.config.codegen.DefParserTest.assertLineFails; import static com.yahoo.config.codegen.DefParserTest.createDefTemplate; import static com.yahoo.config.codegen.DefParserTest.createParser; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; /** * @author gjoranv @@ -20,66 +19,53 @@ public class DefParserNamespaceTest { @Test public void namespace_is_set_on_root_node() { - DefParser parser = createParser("version=1\nnamespace=myproject.config\na string\n"); + DefParser parser = createParser("version=1\nnamespace=myproject.config\n"); CNode root = parser.getTree(); assertThat(root.getNamespace(), is("myproject.config")); } + @Test + public void package_is_used_as_namespace_when_no_namespace_is_given() { + String PACKAGE = "com.github.myproject"; + DefParser parser = createParser("package=" + PACKAGE + "\n"); + CNode root = parser.getTree(); + assertThat(root.getNamespace(), is(PACKAGE)); + } + @Test(expected = CodegenRuntimeException.class) public void uppercase_chars_are_not_allowed() { - createParser("version=1\nnamespace=Foo\na string\n").getTree(); + createParser("version=1\nnamespace=Foo\n").getTree(); } @Test(expected = CodegenRuntimeException.class) public void explicit_com_yahoo_prefix_is_not_allowed() { createParser("version=1\n" + - "namespace=com.yahoo.myproject.config\n" + - "a string\n").getTree(); + "namespace=com.yahoo.myproject.config\n").getTree(); } @Test public void spaces_are_allowed_around_equals_sign() { - DefParser parser = createParser("version=1\nnamespace = myproject.config\na string\n"); + DefParser parser = createParser("version=1\nnamespace = myproject.config\n"); CNode root = parser.getTree(); assertThat(root.getNamespace(), is("myproject.config")); } @Test public void empty_namespace_is_not_allowed() { - // invalid - DefParser parser = createParser("version=1\nnamespace \na string\n"); - try { - parser.getTree(); - fail(); - } catch (Exception e) { - //e.printStackTrace(); - assertExceptionAndMessage(e, CodegenRuntimeException.class, - "Error parsing or reading config definition.Error when parsing line 2: namespace \n" + - "namespace"); - } + assertLineFails("namespace"); } @Test public void consecutive_dots_are_not_allowed() { - // invalid - DefParser parser = createParser("version=1\nnamespace=a..b\na string\n"); - try { - parser.getTree(); - fail(); - } catch (Exception e) { - //e.printStackTrace(); - assertExceptionAndMessage(e, CodegenRuntimeException.class, - "Error parsing or reading config definition.Error when parsing line 2: namespace=a..b\n" + - "namespace=a..b"); - } + assertLineFails("namespace=a..b"); } @Test public void namespace_alters_def_md5() { - DefParser parser = createParser("version=1\na string\n"); + DefParser parser = createParser("version=1\n"); CNode root = parser.getTree(); - parser = createParser("version=1\nnamespace=myproject.config\na string\n"); + parser = createParser("version=1\nnamespace=myproject.config\n"); CNode namespaceRoot = parser.getTree(); assertThat(root.defMd5, not(namespaceRoot.defMd5)); @@ -89,51 +75,30 @@ public class DefParserNamespaceTest { @Test public void number_is_allowed_as_non_leading_char_in_namespace() throws IOException, DefParser.DefParserException { StringBuilder sb = createDefTemplate(); - String line = "namespace=a.b.c2\nfoo int\n"; + String line = "namespace=a.b.c2\n"; sb.append(line); createParser(sb.toString()).parse(); } @Test public void number_is_not_allowed_as_namespace_start_char() throws IOException, DefParser.DefParserException { - StringBuilder sb = createDefTemplate(); - String line = "namespace=2.a.b"; - sb.append(line).append("\n"); - Class<?> exceptionClass = DefParser.DefParserException.class; - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + line + "\n" + line); - } + assertLineFails("namespace=2.a.b"); } @Test public void number_is_not_allowed_as_leading_char_in_namespace_token() throws IOException, DefParser.DefParserException { - StringBuilder sb = createDefTemplate(); - String line = "namespace=a.b.2c"; - sb.append(line).append("\n"); - Class<?> exceptionClass = DefParser.DefParserException.class; - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + line + "\n" + line); - } - + assertLineFails("namespace=a.b.2c"); } @Test public void underscore_in_namespace_is_allowed() throws IOException, DefParser.DefParserException { StringBuilder sb = createDefTemplate(); - String line = "namespace=a_b.c\nfoo int\n"; + String line = "namespace=a_b.c\n"; sb.append(line); createParser(sb.toString()).parse(); sb = createDefTemplate(); - line = "namespace=a_b.c_d\nfoo int\n"; + line = "namespace=a_b.c_d\n"; sb.append(line); createParser(sb.toString()).parse(); } diff --git a/configgen/src/test/java/com/yahoo/config/codegen/DefParserPackageTest.java b/configgen/src/test/java/com/yahoo/config/codegen/DefParserPackageTest.java new file mode 100644 index 00000000000..97986a05bf3 --- /dev/null +++ b/configgen/src/test/java/com/yahoo/config/codegen/DefParserPackageTest.java @@ -0,0 +1,115 @@ +package com.yahoo.config.codegen; + +import org.junit.Test; + +import java.io.IOException; + +import static com.yahoo.config.codegen.DefParser.DEFAULT_PACKAGE_PREFIX; +import static com.yahoo.config.codegen.DefParserTest.assertLineFails; +import static com.yahoo.config.codegen.DefParserTest.createDefTemplate; +import static com.yahoo.config.codegen.DefParserTest.createParser; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.junit.Assert.assertThat; + +/** + * Tests setting explicit java package in the def file. + * + * @author gjoranv + */ +public class DefParserPackageTest { + String PACKAGE = "com.github.myproject"; + + @Test + public void package_is_set_on_root_node() { + DefParser parser = createParser("package=" + PACKAGE + "\n"); + CNode root = parser.getTree(); + assertThat(root.getPackage(), is(PACKAGE)); + } + + @Test + public void package_and_namespace_can_coexist() { + String namespace = "test.namespace"; + DefParser parser = createParser("package=" + PACKAGE + + "\nnamespace=" + namespace +"\n"); + CNode root = parser.getTree(); + assertThat(root.getPackage(), is(PACKAGE)); + assertThat(root.getNamespace(), is(namespace)); + } + + // Required by JavaClassBuilder ctor. + @Test + public void package_is_null_when_not_explicitly_given() { + String namespace = "test.namespace"; + DefParser parser = createParser("namespace=" + namespace + "\n"); + CNode root = parser.getTree(); + assertThat(root.getPackage(), nullValue()); + } + + @Test(expected = CodegenRuntimeException.class) + public void uppercase_chars_are_not_allowed() { + createParser("package=Foo.bar\n").getTree(); + } + + @Test + public void spaces_are_allowed_around_equals_sign() { + DefParser parser = createParser("package = " + PACKAGE + "\n"); + CNode root = parser.getTree(); + assertThat(root.getPackage(), is(PACKAGE)); + } + + @Test + public void empty_package_is_not_allowed() { + assertLineFails("package"); + } + + @Test + public void consecutive_dots_are_not_allowed() { + assertLineFails("package=a..b"); + } + + @Test + public void package_alters_def_md5() { + DefParser parser = createParser("a string\n"); + CNode root = parser.getTree(); + + parser = createParser("package=" + PACKAGE + "\na string\n"); + CNode rootWithPackage = parser.getTree(); + + assertThat(root.defMd5, not(rootWithPackage.defMd5)); + } + + + @Test + public void number_is_allowed_as_non_leading_char() throws IOException, DefParser.DefParserException { + StringBuilder sb = createDefTemplate(); + String line = "package=a.b.c2\n"; + sb.append(line); + createParser(sb.toString()).parse(); + } + + @Test + public void number_is_not_allowed_as_package_start_char() throws IOException, DefParser.DefParserException { + assertLineFails("package=2.a.b"); + } + + @Test + public void number_is_not_allowed_as_leading_char_in_package_token() throws IOException, DefParser.DefParserException { + assertLineFails("package=a.b.2c"); + } + + @Test + public void underscore_in_package_is_allowed() throws IOException, DefParser.DefParserException { + StringBuilder sb = createDefTemplate(); + String line = "package=a_b.c\n"; + sb.append(line); + createParser(sb.toString()).parse(); + + sb = createDefTemplate(); + line = "package=a_b.c_d\n"; + sb.append(line); + createParser(sb.toString()).parse(); + } + +} diff --git a/configgen/src/test/java/com/yahoo/config/codegen/DefParserTest.java b/configgen/src/test/java/com/yahoo/config/codegen/DefParserTest.java index a59a70751b4..e36641bb626 100644 --- a/configgen/src/test/java/com/yahoo/config/codegen/DefParserTest.java +++ b/configgen/src/test/java/com/yahoo/config/codegen/DefParserTest.java @@ -1,7 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. package com.yahoo.config.codegen; -import static org.hamcrest.CoreMatchers.not; import static org.junit.Assert.*; import static org.junit.Assert.assertEquals; @@ -83,16 +82,8 @@ public class DefParserTest { @Test public void testInvalidType() { - Class<?> exceptionClass = DefParser.DefParserException.class; - try { - createParser("version=1\n" + - "# comment\n" + - "a sting").getTree(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage((Exception) e.getCause(), exceptionClass, - "Error when parsing line 3: a sting", false); - } + String line = "a sting"; + assertLineFails(line, "Could not create sting a"); } @Test @@ -116,7 +107,7 @@ public class DefParserTest { } @Test - public void testMissingVersion() { + public void version_is_not_mandatory() { try { createParser("a string\n").parse(); } catch (Exception e) { @@ -148,31 +139,8 @@ public class DefParserTest { @Test public void verify_fail_on_default_for_file() { - Class<?> exceptionClass = DefParser.DefParserException.class; - DefParser parser = createParser("version=1\nf file default=\"file1.txt\"\n"); - try { - parser.getTree(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage((Exception) e.getCause(), exceptionClass, - "Error when parsing line 2: f file default=\"file1.txt\"\n" + - "Invalid default value", false); - } - } - - // Helper method for checking correct exception class and message - static void assertExceptionAndMessage(Exception e, Class<?> exceptionClass, String message) { - assertExceptionAndMessage(e, exceptionClass, message, true); - } - - // Helper method for checking correct exception class and message - static void assertExceptionAndMessage(Exception e, Class<?> exceptionClass, String message, boolean exact) { - if (exact) { - assertEquals(message, e.getMessage()); - } else { - assertTrue(e.getMessage().startsWith(message)); - } - assertEquals(exceptionClass.getName(), e.getClass().getName()); + assertLineFails("f file default=\"file1.txt\"", + "Invalid default value"); } @Test(expected = CodegenRuntimeException.class) @@ -230,180 +198,115 @@ public class DefParserTest { } @Test - public void testInvalidLine() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "a inta\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "Could not create inta a"); - } - } - - @Test - public void testDuplicateDefinition() { + public void duplicate_parameter_is_illegal() { Class<?> exceptionClass = DefParser.DefParserException.class; StringBuilder sb = createDefTemplate(); - String invalidLine = "b int\n"; - sb.append(invalidLine); - // Add a duplicate line, which should be illegal - sb.append(invalidLine); + String duplicateLine = "b int\n"; + sb.append(duplicateLine); + sb.append(duplicateLine); try { createParser(sb.toString()).parse(); fail("Didn't find expected exception of type " + exceptionClass); } catch (Exception e) { assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 4: " + invalidLine + "b is already defined"); + "Error when parsing line 4: " + duplicateLine + "b is already defined"); } } @Test public void testIllegalCharacterInName() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "a-b int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "a-b contains unexpected character"); - } + assertLineFails("a-b int", + "a-b contains unexpected character"); } @Test public void parameter_name_starting_with_digit_is_illegal() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "1a int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "1a must start with a non-digit character"); - } + assertLineFails("1a int", + "1a must start with a non-digit character"); } @Test public void parameter_name_starting_with_uppercase_is_illegal() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "SomeInt int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "'SomeInt' cannot start with an uppercase letter"); - } + assertLineFails("SomeInt int", + "'SomeInt' cannot start with an uppercase letter"); } @Test public void parameter_name_starting_with_the_internal_prefix_is_illegal() { String internalPrefix = ReservedWords.INTERNAL_PREFIX; - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = internalPrefix + "i int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + - "'" + internalPrefix + "i' cannot start with '" + internalPrefix + "'"); - } + assertLineFails(internalPrefix + "i int", + "'" + internalPrefix + "i' cannot start with '" + internalPrefix + "'"); } @Test public void testIllegalArray() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "intArr[ int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "intArr[ Expected ] to terminate array definition"); - } + assertLineFails("intArr[ int", + "intArr[ Expected ] to terminate array definition"); } @Test public void testIllegalDefault() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "a int deflt 10\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + " deflt 10"); - } + assertLineFails("a int deflt 10", + " deflt 10"); } @Test public void testReservedWordInC() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "auto int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "auto is a reserved word in C"); - } + assertLineFails("auto int", + "auto is a reserved word in C"); } @Test public void testReservedWordInJava() { - Class<?> exceptionClass = DefParser.DefParserException.class; - StringBuilder sb = createDefTemplate(); - String invalidLine = "abstract int\n"; - sb.append(invalidLine); - try { - createParser(sb.toString()).parse(); - fail("Didn't find expected exception of type " + exceptionClass); - } catch (Exception e) { - assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "abstract is a reserved word in Java"); - } + assertLineFails("abstract int", + "abstract is a reserved word in Java"); } @Test public void testReservedWordInCAndJava() { - Class<?> exceptionClass = DefParser.DefParserException.class; + assertLineFails("continue int", + "continue is a reserved word in C and Java"); + } + + static StringBuilder createDefTemplate() { + StringBuilder sb = new StringBuilder(); + sb.append("version=8\n"); + // Add a comment line to check that we get correct line number with comments + sb.append("# comment\n"); + + return sb; + } + + static void assertLineFails(String line) { + assertLineFails(line, line); + } + + static void assertLineFails(String line, String message) { StringBuilder sb = createDefTemplate(); - String invalidLine = "continue int\n"; - sb.append(invalidLine); + sb.append(line).append("\n"); + Class<?> exceptionClass = DefParser.DefParserException.class; try { createParser(sb.toString()).parse(); fail("Didn't find expected exception of type " + exceptionClass); } catch (Exception e) { assertExceptionAndMessage(e, exceptionClass, - "Error when parsing line 3: " + invalidLine + "continue is a reserved word in C and Java"); + "Error when parsing line 3: " + line + "\n" + message); } } - static StringBuilder createDefTemplate() { - StringBuilder sb = new StringBuilder(); - sb.append("version=8\n"); - // Add a comment line to check that we get correct line number with comments - sb.append("# comment\n"); + // Helper method for checking correct exception class and message + private static void assertExceptionAndMessage(Exception e, Class<?> exceptionClass, String message) { + assertExceptionAndMessage(e, exceptionClass, message, true); + } - return sb; + // Helper method for checking correct exception class and message + private static void assertExceptionAndMessage(Exception e, Class<?> exceptionClass, String message, boolean exact) { + if (exact) { + assertEquals(message, e.getMessage()); + } else { + assertTrue(e.getMessage().startsWith(message)); + } + assertEquals(exceptionClass.getName(), e.getClass().getName()); } + } |