package org.cloudsmith.geppetto.validation.tests;
import static org.cloudsmith.geppetto.forge.Forge.MODULEFILE_NAME;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.List;
import java.util.Set;
import org.cloudsmith.geppetto.diagnostic.Diagnostic;
import org.cloudsmith.geppetto.diagnostic.FileDiagnostic;
import org.cloudsmith.geppetto.pp.dsl.validation.IPPDiagnostics;
import org.cloudsmith.geppetto.validation.FileType;
import org.cloudsmith.geppetto.validation.IValidationConstants;
import org.cloudsmith.geppetto.validation.ValidationOptions;
import org.cloudsmith.geppetto.validation.ValidationService;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.SubMonitor;
import org.junit.Test;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
public class TestValidatorServiceApi2 extends AbstractValidationTest {
private void assertNotEquals(String message, Object expected, Object actual) {
assertThat(message, expected, not(equalTo(actual)));
}
@Test
public void relativeAmbiguityErrorReport() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/ambiguity/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
ValidationOptions options = getValidationOptions();
options.setCheckLayout(false);
options.setCheckModuleSemantics(false);
options.setCheckReferences(true);
options.setFileType(FileType.MODULE_ROOT);
vs.validate(chain, root, options, null, SubMonitor.convert(null));
assertContainsErrorCode(chain, IPPDiagnostics.ISSUE__RESOURCE_AMBIGUOUS_REFERENCE);
assertTrue(
"Message text should contain a relative reference",
chain.getChildren().get(0).getMessage().startsWith("Ambiguous reference to: 'fluff' found in: 1 resource [") &&
chain.getChildren().get(0).getMessage().contains("manifests/ambigA.pp"));
}
@Test
public void validateAString_NotOk() throws Exception {
String code = "$a = ";
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, code, SubMonitor.convert(null));
assertTrue("There should be errors", countErrors(chain) != 0);
}
@Test
public void validateAString_ok() throws Exception {
String code = "$a = 'a::b'";
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, code, SubMonitor.convert(null));
assertTrue("There should be no errors", countErrors(chain) == 0);
}
@Test
public void validateManifest_notok() throws Exception {
File manifest = TestDataProvider.getTestFile(new Path("testData/manifests/not_ok_manifest.pp"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, manifest, null, null, SubMonitor.convert(null));
assertTrue("There should be errors", countErrors(chain) != 0);
}
@Test
public void validateManifest_ok() throws Exception {
File manifest = TestDataProvider.getTestFile(new Path("testData/manifests/ok_manifest.pp"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, manifest, null, null, SubMonitor.convert(null));
assertTrue("There should be no errors", countErrors(chain) == 0);
}
@Test
public void validateModule_notok() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/broken/broken-module/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, root, null, null, SubMonitor.convert(null));
DiagnosticsAsserter asserter = new DiagnosticsAsserter(chain);
asserter.assertErrors(asserter.messageFragment("unexpected tIDENTIFIER"));
// optionally accept Unknown variables, and hyphen in name, but no other warnings
asserter.assertWarnings(
asserter.issue(IPPDiagnostics.ISSUE__UNKNOWN_VARIABLE).optional().greedy(),
asserter.issue(IPPDiagnostics.ISSUE__HYPHEN_IN_NAME).optional().greedy());
assertEquals("There should be two diagnostic entries", 2, chain.getChildren().size());
}
@Test
public void validateModule_ok() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/test-modules/test-module/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, root, null, null, SubMonitor.convert(null));
DiagnosticsAsserter asserter = new DiagnosticsAsserter(chain);
// no errors
asserter.assertErrors();
// optionally accept Unknown variables, and hyphen in name, but no other warnings
asserter.assertWarnings(
asserter.issue(IPPDiagnostics.ISSUE__UNKNOWN_VARIABLE).optional().greedy(),
asserter.issue(IPPDiagnostics.ISSUE__HYPHEN_IN_NAME).optional().greedy());
assertEquals("There should be one diagnostic entriy", 1, chain.getChildren().size());
}
@Test
public void validateModuleWithSpaces_notok() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/broken withSpaces/module"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, root, null, null, SubMonitor.convert(null));
assertNotEquals("There should be errors", 0, countErrors(chain));
for(Diagnostic d : chain)
if(d instanceof FileDiagnostic) {
File f = ((FileDiagnostic) d).getFile();
assertEquals(
"Reported files should start with 'manifests/'", "manifests/not ok manifest.pp", f.getPath());
}
}
@Test
public void validateRepository_notok() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/forgeModules/lab42-activemq-0.1.2-withErrors/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
ValidationOptions options = getValidationOptions();
options.setCheckLayout(false);
options.setCheckModuleSemantics(true);
options.setCheckReferences(false);
options.setFileType(FileType.MODULE_ROOT);
vs.validate(chain, root, options, null, SubMonitor.convert(null));
assertNotEquals("There should be errors", 0, countErrors(chain));
Set<String> fileNames = Sets.newHashSet();
for(Diagnostic d : chain) {
if("This is not a boolean".equals(d.getMessage()))
continue; // skip this (UGLY)
if(d instanceof FileDiagnostic) {
File f = ((FileDiagnostic) d).getFile();
fileNames.add(f.getPath());
}
}
for(String s : fileNames) {
File f = new File(s);
assertTrue(
"Only files with errors (starts with 'x-', or 'Modulefile') should be reported. Was:" + f.getName(),
f.getName().startsWith("x-") || f.getName().equals(MODULEFILE_NAME));
}
assertEquals("Number of files with errors", 7, fileNames.size());
List<FileDiagnostic> modulefileDiag = Lists.newArrayList();
for(Diagnostic d : chain)
if(d instanceof FileDiagnostic && ((FileDiagnostic) d).getFile().getName().equals(MODULEFILE_NAME))
modulefileDiag.add((FileDiagnostic) d);
assertEquals("There should have been two dependency error", 2, modulefileDiag.size());
for(FileDiagnostic diag : modulefileDiag)
assertEquals(
"Should have been reported as unsatisifed depedency",
IValidationConstants.ISSUE__MODULEFILE_UNSATISFIED_DEPENDENCY, diag.getIssue());
}
@Test
public void validateRepository_ok() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/forgeModules/lab42-activemq-0.1.2/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, root, null, null, SubMonitor.convert(null));
DiagnosticsAsserter asserter = new DiagnosticsAsserter(chain);
asserter.assertAll(asserter.issue(IPPDiagnostics.ISSUE__STRING_BOOLEAN).optional().greedy());
}
@Test
public void validateRepositoryDependencies() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/dependencyCheckData/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
ValidationOptions options = getValidationOptions();
options.setCheckLayout(false);
options.setCheckModuleSemantics(true);
options.setCheckReferences(false);
options.setFileType(FileType.PUPPET_ROOT);
vs.validate(chain, root, options, null, SubMonitor.convert(null));
assertNotEquals("There should be errors", 0, countErrors(chain));
Set<String> fileNames = Sets.newHashSet();
for(Diagnostic d : chain)
if(d instanceof FileDiagnostic && d.getSeverity() >= Diagnostic.ERROR)
fileNames.add(((FileDiagnostic) d).getFile().getPath());
for(String s : fileNames) {
File f = new File(s);
assertTrue(
"Only files with errors (starts with 'x-', or 'Modulefile') should be reported. Was:" + f.getName(),
f.getName().startsWith("x-") || f.getName().equals(MODULEFILE_NAME));
}
assertEquals("Number of files with errors", 1, fileNames.size());
List<FileDiagnostic> modulefileDiag = Lists.newArrayList();
for(Diagnostic d : chain) {
if(d instanceof FileDiagnostic && d.getSeverity() >= Diagnostic.ERROR &&
((FileDiagnostic) d).getFile().getName().equals(MODULEFILE_NAME))
modulefileDiag.add((FileDiagnostic) d);
}
assertEquals("There should have been one dependency error", 1, modulefileDiag.size());
for(FileDiagnostic diag : modulefileDiag)
assertEquals(
"Should have been reported as unsatisifed depedency",
IValidationConstants.ISSUE__MODULEFILE_UNSATISFIED_DEPENDENCY, diag.getIssue());
}
@Test
public void validateRepositoryDependenciesWithExclude() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/dependencyCheckData/"));
ValidationService vs = getValidationService();
ValidationOptions options = getValidationOptions();
Diagnostic chain = new Diagnostic();
options.setCheckLayout(false);
options.setCheckModuleSemantics(true);
options.setCheckReferences(false);
options.setFileType(FileType.PUPPET_ROOT);
vs.validate(chain, root, options, new File[] { new File(root, "moduleB/") }, SubMonitor.convert(null));
assertEquals("There should be no errors", 0, countErrors(chain));
}
@Test
public void validateSeveralRepositories_ok() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/test-modules/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
vs.validate(chain, root, null, null, SubMonitor.convert(null));
int hyphenWarning = 0;
int otherIssues = 0;
for(Diagnostic e : chain)
if(IPPDiagnostics.ISSUE__INTERPOLATED_HYPHEN.equals(e.getIssue()) ||
IPPDiagnostics.ISSUE__HYPHEN_IN_NAME.equals(e.getIssue()))
hyphenWarning++;
else
otherIssues++;
assertEquals("There should be 12 hyphen warnings", 12, hyphenWarning);
assertEquals("There should be 2 other issues", 2, otherIssues);
}
@Test
public void variationsOfValidateCall() throws Exception {
File root = TestDataProvider.getTestFile(new Path("testData/ghbindcases/asmodule/"));
ValidationService vs = getValidationService();
Diagnostic chain = new Diagnostic();
ValidationOptions options = getValidationOptions();
options.setCheckLayout(false);
options.setCheckModuleSemantics(false);
options.setCheckReferences(false);
options.setFileType(FileType.MODULE_ROOT);
vs.validate(chain, root, options, null, SubMonitor.convert(null));
assertContainsErrorCode(chain, IPPDiagnostics.ISSUE__MISSING_COMMA);
// Same but using a repository layout
root = TestDataProvider.getTestFile(new Path("testData/ghbindcases/asrepo/"));
vs = getValidationService();
chain = new Diagnostic();
options = getValidationOptions();
options.setCheckLayout(true);
options.setCheckModuleSemantics(true);
options.setCheckReferences(true);
options.setFileType(FileType.PUPPET_ROOT);
vs.validate(chain, root, options, null, SubMonitor.convert(null));
assertContainsErrorCode(chain, IPPDiagnostics.ISSUE__MISSING_COMMA);
// Use API1 call to do the same as repository layout validation above
vs = getValidationService();
chain = new Diagnostic();
options = getValidationOptions();
options.setCheckLayout(true);
options.setCheckModuleSemantics(true);
options.setCheckReferences(true);
options.setFileType(FileType.PUPPET_ROOT);
vs.validateRepository(chain, root, SubMonitor.convert(null));
assertContainsErrorCode(chain, IPPDiagnostics.ISSUE__MISSING_COMMA);
// just the manifest
root = TestDataProvider.getTestFile(new Path(
"testData/ghbindcases/asmodule/ghoneycutt-bind-1.0.0/manifests/master.pp"));
vs = getValidationService();
chain = new Diagnostic();
options = getValidationOptions();
options.setCheckLayout(false);
options.setCheckModuleSemantics(false);
options.setCheckReferences(false);
options.setFileType(FileType.SINGLE_SOURCE_FILE);
vs.validate(chain, root, options, null, SubMonitor.convert(null));
assertContainsErrorCode(chain, IPPDiagnostics.ISSUE__MISSING_COMMA);
// Validate single file in context of repo
root = TestDataProvider.getTestFile(new Path("testData/ghbindcases/asrepo/"));
vs = getValidationService();
chain = new Diagnostic();
options = getValidationOptions();
options.setCheckLayout(true);
options.setCheckModuleSemantics(true);
options.setCheckReferences(true);
options.setFileType(FileType.PUPPET_ROOT);
vs.validate(chain, root, options, new File[] { new File(
root, "modules/ghoneycutt-bind-1.0.0/manifests/master.pp") }, SubMonitor.convert(null));
assertContainsErrorCode(chain, IPPDiagnostics.ISSUE__MISSING_COMMA);
DiagnosticsAsserter asserter = new DiagnosticsAsserter(chain);
asserter.assertErrors(//
asserter.messageFragment("Unknown class: 'generic'"), //
asserter.messageFragment("Unknown class: 'pam'"), //
asserter.messageFragment("Unknown class: 'ssh'"), //
asserter.messageFragment("Unknown class: 'svn'"), //
asserter.messageFragment("Unknown resource type: 'pam::accesslogin'"), //
asserter.messageFragment("Unknown resource type: 'svn::checkout'"), //
asserter.messageFragment("Missing comma."));
asserter.assertWarnings(asserter.issue(IPPDiagnostics.ISSUE__UNKNOWN_VARIABLE).optional().greedy());
}
}