Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic unit test framework for the validator tool #354

Merged
merged 4 commits into from
Jun 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,15 @@ jobs:
sudo apt-get update
sudo apt-get install openjdk-11-jdk
sudo update-alternatives --set java /usr/lib/jvm/adoptopenjdk-11-hotspot-amd64/bin/java
- name: Running unit tests
- name: Schema unit tests
if: ${{ always() }}
run: bin/test_schema -p
- name: Run registrar validation
- name: Registrar validation
if: ${{ always() }}
run: bin/test_registrar
- name: Validator unit tests
if: ${{ always() }}
run: cd validator; ./gradlew test

ui:
name: UI Tests
Expand Down
3 changes: 2 additions & 1 deletion validator/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ buildscript {

plugins {
id 'com.github.johnrengelman.shadow' version '6.1.0'
id 'com.adarshr.test-logger' version '3.2.0'
id 'java'
id 'checkstyle'
}
Expand All @@ -31,7 +32,7 @@ sourceSets {

checkstyle {
ignoreFailures = false
maxWarnings = 47
maxWarnings = 45
}
checkstyleMain.source = 'src/main/java'

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,12 @@ Set<String> listDevices() {
}
}

/**
* Set the cloud device configuration entry.
*
* @param deviceId target device id
* @param data configuration data blob
*/
public void setDeviceConfig(String deviceId, String data) {
try {
final String registryPath = String.format("projects/%s/locations/%s/registries/%s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@

import java.util.HashMap;

/**
* Collection of metadata for a given project.
*/
public class ProjectMetadata extends HashMap<String, String> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public class Validator {
private String siteDir;
private String deviceId;
private MessagePublisher client;
private Map<String, JsonSchema> schemaMap;

/**
* Create validator for the given project id.
Expand Down Expand Up @@ -163,7 +164,12 @@ public static void main(String[] args) {
System.exit(0);
}

private void setSiteDir(String siteDir) {
/**
* Set the site directory to use for this validation run.
*
* @param siteDir site model directory
*/
public void setSiteDir(String siteDir) {
final File baseDir;
if (NO_SITE.equals(siteDir)) {
this.siteDir = null;
Expand All @@ -180,6 +186,7 @@ private void setSiteDir(String siteDir) {
outBaseDir = new File(baseDir, "out");
outBaseDir.mkdirs();
metadataReportFile = new File(outBaseDir, REPORT_JSON_FILENAME);
System.err.println("Writing validation report to " + metadataReportFile.getAbsolutePath());
metadataReportFile.delete();
}

Expand Down Expand Up @@ -225,7 +232,12 @@ private void initializeFirestoreDataSink() {
// System.err.println("Results will be uploaded to " + dataSink.getViewUrl());
}

private void setSchemaSpec(String schemaPath) {
/**
* Set the schema specification directory.
*
* @param schemaPath schema specification directory
*/
public void setSchemaSpec(String schemaPath) {
File schemaFile = new File(schemaPath).getAbsoluteFile();
if (schemaFile.isFile()) {
schemaRoot = schemaFile.getParentFile();
Expand All @@ -236,6 +248,7 @@ private void setSchemaSpec(String schemaPath) {
} else {
throw new RuntimeException("Schema directory/file not found: " + schemaFile);
}
schemaMap = getSchemaMap();
}

private Map<String, JsonSchema> getSchemaMap() {
Expand All @@ -258,8 +271,7 @@ private BiConsumer<Map<String, Object>, Map<String, String>> messageValidator()
System.err.println("Results may be in such directories as " + outBaseDir.getAbsolutePath());
System.err.println("Generating report file in " + metadataReportFile.getAbsolutePath());

final Map<String, JsonSchema> schemaMap = getSchemaMap();
return (message, attributes) -> validateMessage(schemaMap, message, attributes);
return (message, attributes) -> validateMessage(message, attributes);
}

private void validatePubSub(String instName) {
Expand Down Expand Up @@ -313,8 +325,11 @@ private Set<String> convertIgnoreSet(String ignoreSpec) {
return Arrays.stream(ignoreSpec.split(",")).collect(Collectors.toSet());
}

protected void validateMessage(MessageBundle bundle) {
validateMessage(bundle.message, bundle.attributes);
}

private void validateMessage(
Map<String, JsonSchema> schemaMap,
Map<String, Object> message,
Map<String, String> attributes) {
if (validateUpdate(schemaMap, message, attributes)) {
Expand Down Expand Up @@ -353,10 +368,10 @@ private boolean validateUpdate(
return false;
}

try {
String deviceId = attributes.get("deviceId");
Preconditions.checkNotNull(deviceId, "Missing deviceId in message");
String deviceId = attributes.get("deviceId");
Preconditions.checkNotNull(deviceId, "Missing deviceId in message");

try {
if (expectedDevices.containsKey(deviceId)) {
processedDevices.add(deviceId);
}
Expand All @@ -371,7 +386,7 @@ private boolean validateUpdate(
"Processing device #%d/%d: %s/%s%n",
processedDevices.size(), expectedDevices.size(), deviceId, schemaName);

if (attributes.get("wasBase64").equals("true")) {
if ("true".equals(attributes.get("wasBase64"))) {
base64Devices.add(deviceId);
}

Expand Down Expand Up @@ -447,8 +462,8 @@ private boolean validateUpdate(

return updated;
} catch (Exception e) {
e.printStackTrace();
return false;
getReportingDevice(deviceId).addError(e);
return true;
}
}

Expand Down Expand Up @@ -747,4 +762,10 @@ public InputStream fetch(URI source) {
}
}
}

static class MessageBundle {

public Map<String, Object> message;
public Map<String, String> attributes;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.google.daq.mqtt.validator;

import static org.junit.Assert.assertEquals;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.google.daq.mqtt.validator.Validator.MessageBundle;
import com.google.daq.mqtt.validator.Validator.MetadataReport;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import org.junit.Test;

/**
* Unit test suite for the validator.
*/
public class ValidatorTest {

private static final ObjectMapper OBJECT_MAPPER =
new ObjectMapper()
.enable(SerializationFeature.INDENT_OUTPUT)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.setDateFormat(new ISO8601DateFormat())
.setSerializationInclusion(Include.NON_NULL);

private static final String SCHEMA_SPEC = "../schema";
private static final String SITE_DIR = "../sites/udmi_site_model";
private static final String PROJECT_ID = "ZZ-TRI-FECTA";
private static final String DEVICE_ID = "AHU-1";
private static final File REPORT_FILE = new File(SITE_DIR + "/out/validation_report.json");

private final Validator validator = new Validator(PROJECT_ID);

{
validator.setSchemaSpec(SCHEMA_SPEC);
validator.setSiteDir(SITE_DIR);
}

@Test
public void emptyMessage() {
MessageBundle bundle = new MessageBundle();
bundle.attributes = testMessageAttributes("event", "pointset");
bundle.message = new HashMap<>();
validator.validateMessage(bundle);
MetadataReport report = getMetadataReport();
assertEquals("One error device", report.errorDevices.size(), 1);
}

private MetadataReport getMetadataReport() {
try {
return OBJECT_MAPPER.readValue(REPORT_FILE, MetadataReport.class);
} catch (Exception e) {
throw new RuntimeException("While reading " + REPORT_FILE.getAbsolutePath(), e);
}
}

private Map<String, String> testMessageAttributes(String subType, String subFolder) {
Map<String, String> attributes = new HashMap<>();
attributes.put("deviceRegistryId", PROJECT_ID);
attributes.put("deviceId", DEVICE_ID);
attributes.put("subFolder", subFolder);
attributes.put("subType", subType);
return attributes;
}
}
2 changes: 2 additions & 0 deletions validator/validator.iml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
</content>
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/out" />
Expand Down