package org.gcube.accounting.datamodel.validations.validators; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.FilenameFilter; import java.net.URL; import org.gcube.accounting.aggregator.RegexRulesAggregator; import org.gcube.accounting.datamodel.aggregation.AggregatedServiceUsageRecord; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.documentstore.exception.NotAggregatableRecordsExceptions; import org.gcube.documentstore.records.DSMapper; import org.gcube.testutility.ContextTest; import org.gcube.testutility.TestUsageRecord; import org.junit.Assert; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fasterxml.jackson.databind.ObjectMapper; public class TestRules { private static final Logger logger = LoggerFactory.getLogger(TestRules.class); @Test public void testAllRules() throws Exception { File rulesDirectory = getRulesDirectory(); FilenameFilter filenameFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".json"); } }; File[] rulesFiles = rulesDirectory.listFiles(filenameFilter); RegexRulesAggregator regexRulesAggregator = RegexRulesAggregator.getInstance(); for(File rulesFile : rulesFiles) { ObjectMapper mapper = DSMapper.getObjectMapper(); MatcherReplace matcherReplace = mapper.readValue(rulesFile, MatcherReplace.class); regexRulesAggregator.addMatcherReplace(matcherReplace); } for(File rulesFile : rulesFiles) { testRule(rulesFile); } } public File getRulesDirectory() throws Exception { URL logbackFileURL = TestRules.class.getClassLoader().getResource("logback-test.xml"); File logbackFile = new File(logbackFileURL.toURI()); File resourcesDirectory = logbackFile.getParentFile(); return new File(resourcesDirectory, "rules"); } protected long durationWeightedAverage(int numberA, long durationA, int numberB, long durationB){ return ((numberA * durationA) + (numberB * durationB)) / (numberA + numberB); } public void initAllRules() throws Exception { RegexRulesAggregator regexRulesAggregator = RegexRulesAggregator.getInstance(); File rulesDirectory = getRulesDirectory(); FilenameFilter filenameFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".json"); } }; File[] rulesFiles = rulesDirectory.listFiles(filenameFilter); for(File rulesFile : rulesFiles) { ObjectMapper mapper = DSMapper.getObjectMapper(); MatcherReplace matcherReplace = mapper.readValue(rulesFile, MatcherReplace.class); regexRulesAggregator.addMatcherReplace(matcherReplace); } } public void testRule(File rulesFile) throws Exception { logger.info("-----------------------------------------------------------------------------------------------------"); logger.info("Analisyng rule from file {}\n", rulesFile.getAbsolutePath()); File rulesDirectory = rulesFile.getParentFile(); ObjectMapper mapper = DSMapper.getObjectMapper(); MatcherReplace matcherReplace = mapper.readValue(rulesFile, MatcherReplace.class); Replacer replacer = matcherReplace.getReplacer(); ServiceUsageRecord serviceUsageRecord = TestUsageRecord.createTestServiceUsageRecord(); serviceUsageRecord.setServiceClass(replacer.getServiceClass()); serviceUsageRecord.setServiceName(replacer.getServiceName()); serviceUsageRecord.setCalledMethod(replacer.getCalledMethod()); serviceUsageRecord.validate(); AggregatedServiceUsageRecord aggregated = new AggregatedServiceUsageRecord(serviceUsageRecord); final String requiredMatchesFileName = rulesFile.getName().replaceAll(".json", ".csv"); File elaborationFile = new File(rulesDirectory,requiredMatchesFileName); int count = 1; try(BufferedReader br = new BufferedReader(new FileReader(elaborationFile))) { for(String line; (line = br.readLine()) != null;) { String[] splittedLine = line.split(","); ++count; String serviceClass = splittedLine[0]; String serviceName = splittedLine[1]; String calledMethod = splittedLine[2]; boolean matched = matcherReplace.check(serviceClass,serviceName,calledMethod); if(matched) { logger.info("{} --> {},{},{}", line, replacer.getServiceClass(), replacer.getServiceName(), replacer.getCalledMethod()); } else { logger.error("{} does not match {}. This MUST not occur.", line, matcherReplace.getMultiMatcher().toString()); throw new Exception(); } ServiceUsageRecord sur = TestUsageRecord.createTestServiceUsageRecord(); sur.setServiceClass(serviceClass); sur.setServiceName(serviceName); sur.setCalledMethod(calledMethod); sur.validate(); // logger.trace("To Be aggregated ServiceUsageRecord {}", sur); long minInvocationTime = aggregated.getMinInvocationTime(); long maxInvocationTime = aggregated.getMaxInvocationTime(); long oldDuration = aggregated.getDuration(); long surDuration = sur.getDuration(); aggregated.aggregate(sur); //logger.debug("Resulting Aggregated ServiceUsageRecord: {}", aggregated); long avgDuration = durationWeightedAverage(count-1, oldDuration, 1, surDuration); Assert.assertTrue(aggregated.getDuration() == (avgDuration)); Assert.assertTrue(aggregated.getOperationCount() == count); if(minInvocationTime >= surDuration){ Assert.assertTrue(aggregated.getMinInvocationTime() == surDuration); }else{ Assert.assertTrue(aggregated.getMinInvocationTime() == minInvocationTime); } if(maxInvocationTime >= surDuration){ Assert.assertTrue(aggregated.getMaxInvocationTime() == maxInvocationTime); }else{ Assert.assertTrue(aggregated.getMaxInvocationTime() == surDuration); } } } catch(Exception e) { throw e; } FilenameFilter filenameFilter = new FilenameFilter() { @Override public boolean accept(File dir, String name) { boolean accept = name.endsWith(".csv"); return name.compareTo(requiredMatchesFileName)!=0 && accept; } }; File[] elaborationFilesNoMatch = rulesDirectory.listFiles(filenameFilter); for(File elaborationFileNoMatch : elaborationFilesNoMatch) { logger.info("Comparing examples which must not match from file {}", elaborationFileNoMatch.getName()); try(BufferedReader br = new BufferedReader(new FileReader(elaborationFileNoMatch))) { for(String line; (line = br.readLine()) != null;) { String[] splittedLine = line.split(","); String serviceClass = splittedLine[0]; String serviceName = splittedLine[1]; String calledMethod = splittedLine[2]; boolean matched = matcherReplace.check(serviceClass,serviceName,calledMethod); if(matched) { logger.error("{} match {} but it should NOT. This MUST not occur.", line, matcherReplace.getMultiMatcher().toString()); throw new Exception(); } else { logger.trace("{} does NOT match as requested", line, replacer.getServiceClass(), replacer.getServiceName(), replacer.getCalledMethod()); } ServiceUsageRecord sur = TestUsageRecord.createTestServiceUsageRecord(); sur.setServiceClass(serviceClass); sur.setServiceName(serviceName); sur.setCalledMethod(calledMethod); sur.validate(); //logger.trace("Should not be aggregated ServiceUsageRecord {}", sur); try { aggregated.aggregate(sur); throw new Exception("The record has been aggregated and it should NOT"); }catch (NotAggregatableRecordsExceptions e) { //logger.trace("{} is not aggragable as expected", sur); } } } catch(Exception e) { throw e; } } logger.info("-----------------------------------------------------------------------------------------------------\n\n\n"); } @Test public void testSingleRule() throws Exception { ContextTest.setContextByName(ContextTest.DEFAULT_TEST_SCOPE); initAllRules(); File rulesDirectory = getRulesDirectory(); File rulesFile = new File(rulesDirectory, "geoanalytics-gos-ShapeManagement.json"); testRule(rulesFile); } }