This is an automated email from the ASF dual-hosted git repository.
estrauss pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/systemds.git
The following commit(s) were added to refs/heads/main by this push:
new c4e7e466bc [SYSTEMDS-3842] Improve test coverage of API components:
DMLScript & DMLOptions
c4e7e466bc is described below
commit c4e7e466bc55e39569881bf36b4b88beb016dff0
Author: e-strauss <[email protected]>
AuthorDate: Wed Apr 16 13:08:40 2025 +0200
[SYSTEMDS-3842] Improve test coverage of API components: DMLScript &
DMLOptions
Closes #2241.
---
src/main/java/org/apache/sysds/api/DMLOptions.java | 82 ++---
.../apache/sysds/hops/codegen/SpoofCompiler.java | 2 +-
.../test/component/misc/CLIOptionsParserTest.java | 195 +++++++++++
.../sysds/test/component/misc/DMLScriptTest.java | 364 +++++++++++++++++++++
src/test/resources/conf/invalid-codegen-conf.xml | 23 ++
src/test/resources/conf/invalid-gpu-conf.xml | 22 ++
.../resources/conf/invalid-shadow-buffer1-conf.xml | 23 ++
.../resources/conf/invalid-shadow-buffer2-conf.xml | 23 ++
src/test/resources/conf/shadow-buffer-conf.xml | 23 ++
9 files changed, 716 insertions(+), 41 deletions(-)
diff --git a/src/main/java/org/apache/sysds/api/DMLOptions.java
b/src/main/java/org/apache/sysds/api/DMLOptions.java
index a289b29bcd..763ac7b938 100644
--- a/src/main/java/org/apache/sysds/api/DMLOptions.java
+++ b/src/main/java/org/apache/sysds/api/DMLOptions.java
@@ -141,34 +141,32 @@ public class DMLOptions {
String lineageTypes[] = line.getOptionValues("lineage");
if (lineageTypes != null) {
for (String lineageType : lineageTypes) {
- if (lineageType != null){
- if
(lineageType.equalsIgnoreCase("dedup"))
-
dmlOptions.lineage_dedup = lineageType.equalsIgnoreCase("dedup");
- else if
(lineageType.equalsIgnoreCase("reuse_full")
- ||
lineageType.equalsIgnoreCase("reuse"))
- dmlOptions.linReuseType
= ReuseCacheType.REUSE_FULL;
- else if
(lineageType.equalsIgnoreCase("reuse_partial"))
- dmlOptions.linReuseType
= ReuseCacheType.REUSE_PARTIAL;
- else if
(lineageType.equalsIgnoreCase("reuse_multilevel"))
- dmlOptions.linReuseType
= ReuseCacheType.REUSE_MULTILEVEL;
- else if
(lineageType.equalsIgnoreCase("reuse_hybrid"))
- dmlOptions.linReuseType
= ReuseCacheType.REUSE_HYBRID;
- else if
(lineageType.equalsIgnoreCase("none"))
- dmlOptions.linReuseType
= ReuseCacheType.NONE;
- else if
(lineageType.equalsIgnoreCase("policy_lru"))
-
dmlOptions.linCachePolicy = LineageCachePolicy.LRU;
- else if
(lineageType.equalsIgnoreCase("policy_costnsize"))
-
dmlOptions.linCachePolicy = LineageCachePolicy.COSTNSIZE;
- else if
(lineageType.equalsIgnoreCase("policy_dagheight"))
-
dmlOptions.linCachePolicy = LineageCachePolicy.DAGHEIGHT;
- else if
(lineageType.equalsIgnoreCase("estimate"))
-
dmlOptions.lineage_estimate = lineageType.equalsIgnoreCase("estimate");
- else if
(lineageType.equalsIgnoreCase("debugger"))
-
dmlOptions.lineage_debugger = lineageType.equalsIgnoreCase("debugger");
- else
- throw new
org.apache.commons.cli.ParseException(
- "Invalid
argument specified for -lineage option: " + lineageType);
- }
+ if
(lineageType.equalsIgnoreCase("dedup"))
+ dmlOptions.lineage_dedup =
lineageType.equalsIgnoreCase("dedup");
+ else if
(lineageType.equalsIgnoreCase("reuse_full")
+ ||
lineageType.equalsIgnoreCase("reuse"))
+ dmlOptions.linReuseType =
ReuseCacheType.REUSE_FULL;
+ else if
(lineageType.equalsIgnoreCase("reuse_partial"))
+ dmlOptions.linReuseType =
ReuseCacheType.REUSE_PARTIAL;
+ else if
(lineageType.equalsIgnoreCase("reuse_multilevel"))
+ dmlOptions.linReuseType =
ReuseCacheType.REUSE_MULTILEVEL;
+ else if
(lineageType.equalsIgnoreCase("reuse_hybrid"))
+ dmlOptions.linReuseType =
ReuseCacheType.REUSE_HYBRID;
+ else if
(lineageType.equalsIgnoreCase("none"))
+ dmlOptions.linReuseType =
ReuseCacheType.NONE;
+ else if
(lineageType.equalsIgnoreCase("policy_lru"))
+ dmlOptions.linCachePolicy =
LineageCachePolicy.LRU;
+ else if
(lineageType.equalsIgnoreCase("policy_costnsize"))
+ dmlOptions.linCachePolicy =
LineageCachePolicy.COSTNSIZE;
+ else if
(lineageType.equalsIgnoreCase("policy_dagheight"))
+ dmlOptions.linCachePolicy =
LineageCachePolicy.DAGHEIGHT;
+ else if
(lineageType.equalsIgnoreCase("estimate"))
+ dmlOptions.lineage_estimate =
true;
+ else if
(lineageType.equalsIgnoreCase("debugger"))
+ dmlOptions.lineage_debugger =
true;
+ else
+ throw new
org.apache.commons.cli.ParseException(
+ "Invalid argument
specified for -lineage option: " + lineageType);
}
}
}
@@ -186,13 +184,11 @@ public class DMLOptions {
}
if (line.hasOption("exec")){
String execMode = line.getOptionValue("exec");
- if (execMode != null){
- if (execMode.equalsIgnoreCase("singlenode"))
dmlOptions.execMode = ExecMode.SINGLE_NODE;
- else if (execMode.equalsIgnoreCase("hybrid"))
dmlOptions.execMode = ExecMode.HYBRID;
- else if (execMode.equalsIgnoreCase("spark"))
dmlOptions.execMode = ExecMode.SPARK;
- else throw new
org.apache.commons.cli.ParseException("Invalid argument specified for -exec
option, must be one of [hadoop, singlenode, hybrid, HYBRID, spark]");
- }
- }
+ if (execMode.equalsIgnoreCase("singlenode"))
dmlOptions.execMode = ExecMode.SINGLE_NODE;
+ else if (execMode.equalsIgnoreCase("hybrid"))
dmlOptions.execMode = ExecMode.HYBRID;
+ else if (execMode.equalsIgnoreCase("spark"))
dmlOptions.execMode = ExecMode.SPARK;
+ else throw new
org.apache.commons.cli.ParseException("Invalid argument specified for -exec
option, must be one of [hadoop, singlenode, hybrid, HYBRID, spark]");
+ }
if (line.hasOption("explain")) {
dmlOptions.explainType = ExplainType.RUNTIME;
String explainType = line.getOptionValue("explain");
@@ -222,7 +218,7 @@ public class DMLOptions {
dmlOptions.statsNGrams = line.hasOption("ngrams");
if (dmlOptions.statsNGrams){
String[] nGramArgs = line.getOptionValues("ngrams");
- if (nGramArgs.length >= 2) {
+ if (nGramArgs != null && nGramArgs.length >= 2) {
try {
String[] nGramSizeSplit =
nGramArgs[0].split(",");
dmlOptions.statsNGramSizes = new
int[nGramSizeSplit.length];
@@ -273,11 +269,17 @@ public class DMLOptions {
if (line.hasOption("fedMonitoring")) {
dmlOptions.fedMonitoring= true;
- dmlOptions.fedMonitoringPort =
Integer.parseInt(line.getOptionValue("fedMonitoring"));
+ String port = line.getOptionValue("fedMonitoring");
+ if(port != null)
+ dmlOptions.fedMonitoringPort =
Integer.parseInt(port);
+ else
+ throw new
org.apache.commons.cli.ParseException("No port [integer] specified for
-fedMonitoring option");
}
if (line.hasOption("fedMonitoringAddress")) {
dmlOptions.fedMonitoringAddress =
line.getOptionValue("fedMonitoringAddress");
+ if(dmlOptions.fedMonitoringAddress == null)
+ throw new
org.apache.commons.cli.ParseException("No address [String] specified for
-fedMonitoringAddress option");
}
if (line.hasOption("f")){
@@ -326,7 +328,7 @@ public class DMLOptions {
OptimizerUtils.FEDERATED_COMPILATION = true;
dmlOptions.federatedCompilation = true;
String[] fedCompSpecs =
line.getOptionValues("federatedCompilation");
- if ( fedCompSpecs != null && fedCompSpecs.length > 0 ){
+ if (fedCompSpecs != null){
for ( String spec : fedCompSpecs ){
String[] specPair = spec.split("=");
if (specPair.length != 2){
@@ -370,8 +372,8 @@ public class DMLOptions {
.withDescription("monitors and reports summary
execution statistics; heavy hitter <count> is 10 unless overridden; default
off")
.hasOptionalArg().create("stats");
Option ngramsOpt = OptionBuilder//.withArgName("ngrams")
- .withDescription("monitors and reports the most
occurring n-grams; -ngrams <comma separated n's> <topK>")
- .hasOptionalArgs(2).create("ngrams");
+ .withDescription("monitors and reports the most
occurring n-grams; -ngrams <comma separated n's> <topK> <boolean lineage>")
+ .hasOptionalArgs(3).create("ngrams");
Option fedStatsOpt = OptionBuilder.withArgName("count")
.withDescription("monitors and reports summary
execution statistics of federated workers; heavy hitter <count> is 10 unless
overridden; default off")
.hasOptionalArg().create("fedStats");
diff --git a/src/main/java/org/apache/sysds/hops/codegen/SpoofCompiler.java
b/src/main/java/org/apache/sysds/hops/codegen/SpoofCompiler.java
index c0e1a2a320..34329ca64d 100644
--- a/src/main/java/org/apache/sysds/hops/codegen/SpoofCompiler.java
+++ b/src/main/java/org/apache/sysds/hops/codegen/SpoofCompiler.java
@@ -223,7 +223,7 @@ public class SpoofCompiler {
else {
local_tmp = System.getProperty("user.dir") +
"/src/main".replace("/", File.separator);
}
-
+ // TODO: Code is unreachable here
if(generator == GeneratorAPI.CUDA) {
// init GPUs with jCuda to avoid double
initialization problems
GPUContextPool.initializeGPU();
diff --git
a/src/test/java/org/apache/sysds/test/component/misc/CLIOptionsParserTest.java
b/src/test/java/org/apache/sysds/test/component/misc/CLIOptionsParserTest.java
index 3e6239b5e4..ec8843440a 100644
---
a/src/test/java/org/apache/sysds/test/component/misc/CLIOptionsParserTest.java
+++
b/src/test/java/org/apache/sysds/test/component/misc/CLIOptionsParserTest.java
@@ -24,6 +24,9 @@ import java.util.Map;
import org.apache.commons.cli.AlreadySelectedException;
import org.apache.commons.cli.MissingOptionException;
import org.apache.commons.cli.ParseException;
+import org.apache.sysds.hops.OptimizerUtils;
+import org.apache.sysds.runtime.instructions.fed.FEDInstruction;
+import org.apache.sysds.runtime.lineage.LineageCacheConfig;
import org.junit.Assert;
import org.junit.Test;
import org.apache.sysds.api.DMLOptions;
@@ -31,6 +34,8 @@ import org.apache.sysds.common.Types.ExecMode;
import org.apache.sysds.runtime.lineage.LineageCacheConfig.ReuseCacheType;
import org.apache.sysds.utils.Explain;
+import static org.apache.sysds.api.DMLOptions.parseCLArguments;
+
@net.jcip.annotations.NotThreadSafe
public class CLIOptionsParserTest {
@@ -162,6 +167,7 @@ public class CLIOptionsParserTest {
Assert.assertEquals(ReuseCacheType.REUSE_PARTIAL,
o.linReuseType);
Assert.assertEquals(false, o.lineage_dedup);
}
+
@Test
public void testLineageReuseH() throws Exception {
String cl = "systemds -f test.dml -lineage reuse_hybrid";
@@ -450,4 +456,193 @@ public class CLIOptionsParserTest {
Map<String, String> m = o.argVals;
Assert.assertEquals("'def'", m.get("$abc"));
}
+
+ @Test
+ public void parseCLArgumentsLineageDAGHEIGHTTest() throws
ParseException {
+ String[] args = new String[]{"-f", "test", "-lineage",
"policy_dagheight"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.lineage && opts.linCachePolicy ==
LineageCacheConfig.LineageCachePolicy.DAGHEIGHT);
+ }
+
+ @Test
+ public void parseCLIArgumentsLineageEstimateTest() throws
ParseException {
+ String[] args = new String[]{"-f", "test", "-lineage",
"estimate"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.lineage && opts.lineage_estimate);
+ }
+
+ @Test
+ public void parseCLArgumentsGPUTest() throws ParseException {
+ String[] args = new String[]{"-f", "test", "-gpu",};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.gpu);
+ }
+
+ @Test
+ public void parseCLArgumentsInvalidExplainTest() throws ParseException {
+ String[] args = new String[]{"-f", "test","-explain","XYZ"};
+ try {
+ parseCLArguments(args);
+ } catch (ParseException e) {
+ assert e.getMessage().equals("Invalid argument
specified for -hops option, must be one of [hops, runtime, recompile_hops,
recompile_runtime, codegen, codegen_recompile]");
+ }
+ }
+
+ @Test
+ public void parseCLArgumentsExplainCodegenRecompileTest() throws
ParseException {
+ String[] args = new String[]{"-f",
"test","-explain","codegen_recompile"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertEquals(opts.explainType,
Explain.ExplainType.CODEGEN_RECOMPILE);
+ }
+
+ @Test
+ public void parseCLArgumentsNGramsTest1() throws ParseException {
+ String[] args = new String[]{"-f", "test", "-ngrams",};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.statsNGrams);
+ }
+
+ @Test
+ public void parseCLArgumentsNGramsTest2() throws ParseException {
+ String[] args = new String[]{"-f", "test", "-ngrams","1"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.statsNGrams);
+ }
+
+ @Test
+ public void parseCLArgumentsNGramsTest3() throws ParseException {
+ String[] args = new String[]{"-f", "test",
"-ngrams","1","1","FALSE"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.statsNGrams);
+ Assert.assertEquals(opts.statsNGramSizes[0], 1);
+ Assert.assertEquals(opts.statsTopKNGrams, 1);
+ Assert.assertFalse(opts.statsNGramsUseLineage);
+ }
+
+ @Test
+ public void parseCLArgumentsNGramsTest4() throws ParseException {
+ String[] args = new String[]{"-f", "test", "-ngrams","1,3","1"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.statsNGrams);
+ Assert.assertEquals(opts.statsNGramSizes[0], 1);
+ Assert.assertEquals(opts.statsNGramSizes[1], 3);
+ Assert.assertEquals(opts.statsTopKNGrams, 1);
+ Assert.assertTrue(opts.statsNGramsUseLineage);
+ }
+
+ @Test
+ public void parseCLArgumentsNGramsTest5() throws ParseException {
+ String[] args = new String[]{"-f", "test","-ngrams","1,2","b"};
+ try {
+ parseCLArguments(args);
+ } catch (ParseException e) {
+ assert e.getMessage().equals("Invalid argument
specified for -ngrams option, must be a valid integer");
+ }
+ }
+
+ @Test
+ public void parseCLArgumentsFEDStatsTest1() throws ParseException {
+ String[] args = new String[]{"-f", "test", "-fedStats",};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.fedStats);
+ }
+
+ @Test
+ public void parseCLArgumentsFEDStatsTest2() throws ParseException {
+ String[] args = new String[]{"-f", "test", "-fedStats", "21"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.fedStats);
+ Assert.assertEquals(21, opts.fedStatsCount);
+ }
+
+ @Test
+ public void parseCLArgumentsFEDStatsTest3() {
+ String[] args = new String[]{"-f", "test", "-fedStats", "xyz"};
+ try {
+ parseCLArguments(args);
+ } catch (ParseException e) {
+ assert e.getMessage().equals("Invalid argument
specified for -fedStats option, must be a valid integer");
+ }
+ }
+
+ @Test
+ public void parseCLArgumentsFEDMonitoringTest1() {
+ String[] args = new String[]{"-fedMonitoring"};
+ try {
+ parseCLArguments(args);
+ } catch (ParseException e) {
+ assert e.getMessage().equals("No port [integer]
specified for -fedMonitoring option");
+ }
+ }
+
+ @Test
+ public void parseCLArgumentsFEDMonitoringTest2() {
+ String[] args = new String[]{"-fedMonitoring","21",
"-fedMonitoringAddress"};
+ try {
+ parseCLArguments(args);
+ } catch (ParseException e) {
+ assert e.getMessage().equals("No address [String]
specified for -fedMonitoringAddress option");
+ }
+ }
+
+ @Test
+ public void parseCLArgumentsFEDMonitoringTest3() throws ParseException {
+ String[] args = new String[]{"-fedMonitoring", "21"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.fedMonitoring);
+ Assert.assertEquals(21, opts.fedMonitoringPort);
+ }
+
+ @Test
+ public void parseCLArgumentsFEDMonitoringTest4() throws ParseException {
+ String[] args = new String[]{"-fedMonitoring", "21",
"-fedMonitoringAddress", "xyz"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.fedMonitoring);
+ Assert.assertEquals(21, opts.fedMonitoringPort);
+ Assert.assertEquals("xyz", opts.fedMonitoringAddress);
+ }
+
+ @Test
+ public void parseCLArgumentsFEDCompilationTest1() throws ParseException
{
+ String[] args = new String[]{"-f", "test",
"-federatedCompilation"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.federatedCompilation);
+ }
+
+ @Test
+ public void parseCLArgumentsFEDCompilationTest2() throws ParseException
{
+ String[] args = new String[]{"-f", "test",
"-federatedCompilation", "1=NONE"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.federatedCompilation);
+ Assert.assertEquals(OptimizerUtils.FEDERATED_SPECS.get(1),
FEDInstruction.FederatedOutput.NONE);
+ }
+
+ @Test
+ public void parseCLArgumentsFEDCompilationTest3() {
+ String[] args = new String[]{"-f","test",
"-federatedCompilation","1=n=n"};
+ try {
+ parseCLArguments(args);
+ throw new AssertionError("Test should have resulted in
Exception");
+ } catch (ParseException e){
+ Assert.assertEquals("Invalid argument specified for
-federatedCompilation option, must be a list of space separated K=V pairs,
where K is a line number of the DML script and V is a federated output
value",e.getMessage());
+ }
+ }
+
+ @Test
+ public void parseCLArgumentsFEDNoRuntimeConversionTest() throws
ParseException {
+ String[] args = new String[]{"-f", "test",
"-noFedRuntimeConversion"};
+ DMLOptions opts = parseCLArguments(args);
+ Assert.assertTrue(opts.noFedRuntimeConversion);
+ }
+
+ @Test
+ public void testDMLOptionToString() throws ParseException {
+ String cl = "systemds -f test.dml -exec spark";
+ String[] args = cl.split(" ");
+ DMLOptions o = DMLOptions.parseCLArguments(args);
+ String oString = o.toString();
+ Assert.assertTrue(oString.contains("script='null'"));
+ Assert.assertTrue(oString.contains("filePath='test.dml'"));
+ Assert.assertTrue(oString.contains("execMode=SPARK"));
+ }
}
\ No newline at end of file
diff --git
a/src/test/java/org/apache/sysds/test/component/misc/DMLScriptTest.java
b/src/test/java/org/apache/sysds/test/component/misc/DMLScriptTest.java
new file mode 100644
index 0000000000..5b5483823a
--- /dev/null
+++ b/src/test/java/org/apache/sysds/test/component/misc/DMLScriptTest.java
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+package org.apache.sysds.test.component.misc;
+
+
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.spi.LoggingEvent;
+import org.apache.sysds.api.DMLOptions;
+import org.apache.sysds.api.DMLScript;
+import org.apache.sysds.parser.LanguageException;
+import org.apache.sysds.test.LoggingUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static org.apache.sysds.api.DMLScript.executeScript;
+import static org.apache.sysds.api.DMLScript.readDMLScript;
+
[email protected]
+public class DMLScriptTest {
+
+ @Test
+ public void executeDMLScriptParsingExceptionTest() throws IOException {
+ // Create a ListAppender to capture log messages
+ final LoggingUtils.TestAppender appender = LoggingUtils.overwrite();
+ try {
+ Logger.getLogger(DMLScript.class).setLevel(Level.DEBUG);
+
+ String[] args = new String[]{"-f", "test","-explain","XYZ"};
+ Assert.assertFalse(executeScript(args));
+
+ final List<LoggingEvent> log = LoggingUtils.reinsert(appender);
+ Assert.assertEquals(log.get(0).getMessage(), "Parsing Exception
Invalid argument specified for -hops option, must be one of [hops, runtime,
recompile_hops, recompile_runtime, codegen, codegen_recompile]");
+ } finally {
+ LoggingUtils.reinsert(appender);
+ }
+ }
+
+ @Test
+ public void executeDMLScriptAlreadySelectedExceptionTest() throws
IOException {
+ final LoggingUtils.TestAppender appender = LoggingUtils.overwrite();
+ try {
+ Logger.getLogger(DMLScript.class).setLevel(Level.DEBUG);
+
+ String[] args = new String[]{"-f", "test", "-clean"};
+ Assert.assertFalse(executeScript(args));
+
+ final List<LoggingEvent> log = LoggingUtils.reinsert(appender);
+ Assert.assertEquals(log.get(0).getMessage(), "Mutually exclusive
options were selected. The option 'clean' was specified but an option from this
group has already been selected: 'f'");
+ } finally {
+ LoggingUtils.reinsert(appender);
+ }
+ }
+
+ @Test
+ public void executeDMLHelpTest() throws IOException {
+ String[] args = new String[]{"-help"};
+ Assert.assertTrue(executeScript(args));
+ }
+
+ @Test
+ public void executeDMLCleanTest() throws IOException {
+ String[] args = new String[]{"-clean"};
+ Assert.assertTrue(executeScript(args));
+ }
+
+ @Test
+ public void executeDMLfedMonitoringTest() {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ try {
+ String[] args = new String[]{"-fedMonitoring", "1"};
+ Future<?> future = executor.submit(() -> executeScript(args));
+
+ try {
+ future.get(10, TimeUnit.SECONDS); // Wait for up to 10 seconds
+ } catch (TimeoutException e) {
+ future.cancel(true); // Cancel if timeout occurs
+ System.out.println("Test fedMonitoring was forcefully
terminated after 10s.");
+ } catch (Exception e) {
+ future.cancel(true); // Cancel in case of any other failure
+ throw new RuntimeException("Test execution failed", e);
+ }
+ } finally {
+ executor.shutdownNow();
+ }
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void executeDMLfedMonitoringAddressTest1() throws Throwable {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ try {
+ String[] args = new
String[]{"-f","src/test/scripts/usertest/helloWorld.dml","-fedMonitoringAddress",
+ "http://localhost:8080"};
+ Future<?> future = executor.submit(() -> executeScript(args));
+ try {
+ future.get(10, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ future.cancel(true);
+ System.out.println("Test fedMonitoring was forcefully
terminated after 10s.");
+ } catch (Exception e) {
+ future.cancel(true);
+ throw e.getCause();
+ }
+ } finally {
+ executor.shutdownNow();
+ DMLScript.MONITORING_ADDRESS = null;
+ }
+ }
+
+ @Test
+ public void executeDMLfedMonitoringAddressTest2() throws Throwable {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ try {
+ String[] args = new
String[]{"-f","src/test/scripts/usertest/helloWorld.dml","-fedMonitoringAddress",
+ "https://example.com"};
+ Future<?> future = executor.submit(() -> executeScript(args));
+ try {
+ future.get(10, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ future.cancel(true);
+ System.out.println("Test fedMonitoring was forcefully
terminated after 10s.");
+ } catch (Exception e) {
+ future.cancel(true);
+ throw e.getCause();
+ }
+ } finally {
+ executor.shutdownNow();
+ DMLScript.MONITORING_ADDRESS = null;
+ }
+ }
+
+ @Test
+ public void executeDMLWithScriptTest() throws IOException {
+ String cl = "systemds -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ final PrintStream originalOut = System.out;
+ final ByteArrayOutputStream outputStreamCaptor = new
ByteArrayOutputStream();
+
+ System.setOut(new PrintStream(outputStreamCaptor));
+ try{
+ Assert.assertTrue(executeScript(args));
+ Assert.assertEquals("hello",
outputStreamCaptor.toString().split(System.lineSeparator())[0]);
+ } finally {
+ System.setOut(originalOut);
+ }
+ }
+
+ @Test(expected = LanguageException.class)
+ public void readDMLWithNoScriptTest() throws IOException {
+ readDMLScript(false, null);
+ }
+
+ @Test(expected = LanguageException.class)
+ public void readDMLWithNoFilepathTest() throws IOException {
+ readDMLScript(true, null);
+ }
+
+ @Test(expected = IOException.class)
+ public void readDMLWrongHDFSPathTest1() throws IOException {
+ readDMLScript(true, "hdfs:/namenodehost/test.txt");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void readDMLWrongHDFSPathTes2t() throws IOException {
+ readDMLScript(true, "hdfs://namenodehost/test.txt");
+ }
+
+ @Test(expected = IOException.class)
+ public void readDMLWrongGPFSPathTest() throws IOException {
+ readDMLScript(true, "gpfs:/namenodehost/test.txt");
+ }
+
+ @Test
+ public void setActiveAMTest(){
+ DMLScript.setActiveAM();
+ try {
+
+ Assert.assertTrue(DMLScript.isActiveAM());
+ } finally {
+ DMLScript._activeAM = false;
+ }
+ }
+
+ @Test
+ public void runDMLScriptMainLanguageExceptionTest(){
+ String cl = "systemds -debug -s \"printx('hello')\"";
+ String[] args = cl.split(" ");
+ final PrintStream originalErr = System.err;
+
+ try {
+ final ByteArrayOutputStream outputStreamCaptor = new
ByteArrayOutputStream();
+ System.setErr(new PrintStream(outputStreamCaptor));
+ DMLScript.main(args);
+ System.setErr(originalErr);
+
Assert.assertTrue(outputStreamCaptor.toString().split(System.lineSeparator())[0]
+ .startsWith("org.apache.sysds.parser.LanguageException:
ERROR: [line 1:0] -> printx('hello') -- function printx is undefined"));
+ } finally {
+ System.setErr(originalErr);
+ }
+
+ }
+
+ @Test
+ public void runDMLScriptMainDMLRuntimeExceptionTest(){
+ String cl = "systemds -s
\"F=as.frame(matrix(1,1,1));spec=\"{ids:true,recod:[1]}\";" +
+ "M=transformapply(target=F,spec=spec,meta=F);print(M[1,1]) \"";
+ String[] args = cl.split(" ");
+
+ final PrintStream originalOut = System.out;
+ try {
+ final ByteArrayOutputStream outputStreamCaptor = new
ByteArrayOutputStream();
+ System.setOut(new PrintStream(outputStreamCaptor));
+ DMLScript.main(args);
+ System.setOut(originalOut);
+ String[] lines =
outputStreamCaptor.toString().split(System.lineSeparator());
+ for (int i = 0; i < lines.length; i++) {
+ if(lines[i].startsWith("An Error Occurred :")){
+ for (int j = 0; j < 4; j++) {
+ Assert.assertTrue(lines[i + 1 +
j].trim().startsWith("DMLRuntimeException"));
+ }
+ break;
+ }
+ }
+ } finally {
+ System.setOut(originalOut);
+ }
+
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void executeDMLWithScriptInvalidConfTest1() throws IOException {
+ String cl = "systemds -config
src/test/resources/conf/invalid-gpu-conf.xml -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ executeScript(args);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void executeDMLWithScriptInvalidConfTest2() throws IOException {
+ String cl = "systemds -config
src/test/resources/conf/invalid-shadow-buffer1-conf.xml -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ executeScript(args);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void executeDMLWithScriptInvalidConfTest3() throws IOException {
+ String cl = "systemds -config
src/test/resources/conf/invalid-shadow-buffer2-conf.xml -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ executeScript(args);
+ }
+
+ @Test
+ public void executeDMLWithScriptValidCodegenConfTest() throws IOException {
+ String cl = "systemds -config
src/test/resources/conf/invalid-codegen-conf.xml -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ executeScript(args);
+ }
+
+ @Test
+ public void executeDMLWithScriptShadowBufferWarnTest() throws IOException {
+ String cl = "systemds -config
src/test/resources/conf/shadow-buffer-conf.xml -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ DMLScript.EVICTION_SHADOW_BUFFER_CURR_BYTES =1000000000L;
+
+ final PrintStream originalOut = System.out;
+ try {
+ final ByteArrayOutputStream outputStreamCaptor = new
ByteArrayOutputStream();
+ System.setOut(new PrintStream(outputStreamCaptor));
+ executeScript(args);
+ System.setOut(originalOut);
+ String[] lines =
outputStreamCaptor.toString().split(System.lineSeparator());
+ Assert.assertTrue(lines[0].startsWith("WARN: Cannot use the shadow
buffer due to potentially cached GPU objects. Current shadow buffer size (in
bytes)"));
+ } finally {
+ System.setOut(originalOut);
+ }
+ }
+
+ @Test
+ public void executeDMLWithScriptAndInfoTest() throws IOException {
+ String cl = "systemds -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+ Logger.getLogger(DMLScript.class).setLevel(Level.INFO);
+ final LoggingUtils.TestAppender appender = LoggingUtils.overwrite();
+ try {
+ Assert.assertTrue(executeScript(args));
+ final List<LoggingEvent> log = LoggingUtils.reinsert(appender);
+ try {
+ int i = log.get(0).getMessage().toString().startsWith("Low
memory budget") ? 1 : 0;
+
Assert.assertTrue(log.get(i++).getMessage().toString().startsWith("BEGIN DML
run"));
+
Assert.assertTrue(log.get(i).getMessage().toString().startsWith("Process id"));
+ } catch (Error e) {
+ System.out.println("ERROR while evaluating INFO logs: ");
+ for (LoggingEvent loggingEvent : log) {
+ System.out.println(loggingEvent.getMessage());
+ }
+ throw e;
+ }
+
+ } finally {
+ LoggingUtils.reinsert(appender);
+ }
+ }
+
+ @Test
+ public void executeDMLWithScriptAndDebugTest() throws IOException {
+ // have to run sequentially, to avoid concurrent call to
Logger.getLogger(DMLScript.class)
+ String cl = "systemds -s \"print('hello')\"";
+ String[] args = cl.split(" ");
+
+ Logger.getLogger(DMLScript.class).setLevel(Level.DEBUG);
+ final LoggingUtils.TestAppender appender2 = LoggingUtils.overwrite();
+ try{
+ Assert.assertTrue(executeScript(args));
+ final List<LoggingEvent> log = LoggingUtils.reinsert(appender2);
+ try {
+ int i = log.get(0).getMessage().toString().startsWith("Low
memory budget") ? 2 : 1;
+
Assert.assertTrue(log.get(i++).getMessage().toString().startsWith("BEGIN DML
run"));
+
Assert.assertTrue(log.get(i++).getMessage().toString().startsWith("DML
script"));
+
Assert.assertTrue(log.get(i).getMessage().toString().startsWith("Process id"));
+ } catch (Error e){
+ for (LoggingEvent loggingEvent : log) {
+ System.out.println(loggingEvent.getMessage());
+ }
+ throw e;
+ }
+ } finally {
+ LoggingUtils.reinsert(appender2);
+ }
+ }
+
+ @Test
+ public void createDMLScriptInstance(){
+ DMLScript script = new DMLScript();
+ Assert.assertTrue(script != null);
+ }
+}
diff --git a/src/test/resources/conf/invalid-codegen-conf.xml
b/src/test/resources/conf/invalid-codegen-conf.xml
new file mode 100644
index 0000000000..df1be48365
--- /dev/null
+++ b/src/test/resources/conf/invalid-codegen-conf.xml
@@ -0,0 +1,23 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<root>
+ <sysds.codegen.enabled>true</sysds.codegen.enabled>
+ <sysds.codegen.api>CUDA</sysds.codegen.api>
+</root>
diff --git a/src/test/resources/conf/invalid-gpu-conf.xml
b/src/test/resources/conf/invalid-gpu-conf.xml
new file mode 100644
index 0000000000..28a7f595c7
--- /dev/null
+++ b/src/test/resources/conf/invalid-gpu-conf.xml
@@ -0,0 +1,22 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<root>
+ <sysds.gpu.memory.util.factor>-1</sysds.gpu.memory.util.factor>
+</root>
diff --git a/src/test/resources/conf/invalid-shadow-buffer1-conf.xml
b/src/test/resources/conf/invalid-shadow-buffer1-conf.xml
new file mode 100644
index 0000000000..6574d3c1ac
--- /dev/null
+++ b/src/test/resources/conf/invalid-shadow-buffer1-conf.xml
@@ -0,0 +1,23 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<root>
+ <sysds.floating.point.precision>single</sysds.floating.point.precision>
+
<sysds.gpu.eviction.shadow.bufferSize>2</sysds.gpu.eviction.shadow.bufferSize>
+</root>
diff --git a/src/test/resources/conf/invalid-shadow-buffer2-conf.xml
b/src/test/resources/conf/invalid-shadow-buffer2-conf.xml
new file mode 100644
index 0000000000..33203bb255
--- /dev/null
+++ b/src/test/resources/conf/invalid-shadow-buffer2-conf.xml
@@ -0,0 +1,23 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<root>
+ <sysds.floating.point.precision>single</sysds.floating.point.precision>
+
<sysds.gpu.eviction.shadow.bufferSize>-1</sysds.gpu.eviction.shadow.bufferSize>
+</root>
diff --git a/src/test/resources/conf/shadow-buffer-conf.xml
b/src/test/resources/conf/shadow-buffer-conf.xml
new file mode 100644
index 0000000000..ddc32be334
--- /dev/null
+++ b/src/test/resources/conf/shadow-buffer-conf.xml
@@ -0,0 +1,23 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<root>
+ <sysds.floating.point.precision>single</sysds.floating.point.precision>
+
<sysds.gpu.eviction.shadow.bufferSize>0.01</sysds.gpu.eviction.shadow.bufferSize>
+</root>