diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizationTask.java b/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizationTask.java index 014aa20fa7..2141d58cb1 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizationTask.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/OptimizationTask.java @@ -105,7 +105,7 @@ public Scalar value( this.update.apply( tojo, this.make( - this.optimization(tojo, common).apply(new XMLDocument(src)), src + this.optimization(tojo, common).apply(src), src ).toAbsolutePath() ); return 1; diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptCached.java b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptCached.java index 8357a97576..4ce47507f2 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptCached.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptCached.java @@ -25,13 +25,10 @@ import com.jcabi.xml.XML; import com.jcabi.xml.XMLDocument; +import java.io.FileNotFoundException; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; -import java.util.Optional; import org.eolang.maven.AssembleMojo; import org.eolang.maven.Place; import org.eolang.maven.footprint.FtDefault; @@ -41,19 +38,14 @@ * Returns already optimized XML if it's found in the cache. * * @since 0.28.11 - * @todo #2746:30min Fix caching mechanism in {@link OptCached}. Current - * The last modified time of the files between stages may be different, - * so it is not correct to do an equality comparison ({@code .equals(...)}). - * The last modification time of the file at the current stage - * must be less than or equal to the last modification time of file in cache at the next stage. - * The following tests show that fetching from the cache doesn't work correctly: - * - {@link OptCachedTest#returnsFromCacheCorrectProgram(Path path)}, - * - {@link OptCachedTest#returnsFromCacheButTimesSaveAndExecuteDifferent(Path path)}. * @todo #2746:30min Unify caching mechanism on stages: parse, optimize, pull and so on. * Current implementations of caching on parsing stage and optimize stages work differently. * In ParseMojo we have condition {@code if (tojo.hasHash()) }, in OptimizeMojo or ShakeMojo we * compare creation time of files. * Don't forget to enable the tests. + * @todo #2791:30min Get the XML name from its path, + * but doesn't use {@code xml.xpath("/program/@name").get(0)}, + * in classes {@link OptCached}, {@link OptTrain}, {@link OptSpy}. */ public final class OptCached implements Optimization { @@ -82,54 +74,60 @@ public OptCached( } @Override - public XML apply(final XML xml) { + public XML apply(final Path path) throws FileNotFoundException { try { final XML optimized; - if (this.contains(xml)) { - optimized = new XMLDocument(this.cached(xml)); + if (this.contains(path)) { + optimized = new XMLDocument(this.cached(path)); } else { - optimized = this.delegate.apply(xml); + optimized = this.delegate.apply(path); new FtDefault(this.folder).save( - xml.xpath("/program/@name").get(0), + new XMLDocument(path).xpath("/program/@name").get(0), AssembleMojo.IR_EXTENSION, optimized::toString ); } return optimized; } catch (final IOException ex) { - throw new IllegalStateException(String.format("Can't optimize '%s'", xml), ex); + throw new IllegalStateException( + String.format("Can't optimize '%s'", new XMLDocument(path)), + ex + ); } } /** * Returns the path to the cached program. * Pay attention that the path is not checked for existence. - * @param xml Eo program. + * @param path Path eo program. * @return Path to the cached program. + * @throws IOException If fails. */ - private Path cached(final XML xml) { - return new Place(xml.xpath("/program/@name").get(0)) + private Path cached(final Path path) throws IOException { + return new Place( + new XMLDocument(path) + .xpath("/program/@name").get(0) + ) .make(this.folder, AssembleMojo.IR_EXTENSION); } /** * Checks if the cache contains the program. - * @param xml Eo program. + * @param path Path eo program. * @return True if the cache contains the program. * @throws IOException If fails. */ - private boolean contains(final XML xml) throws IOException { - final Path path = this.cached(xml); - final Optional time = xml.xpath("/program/@time").stream().findFirst(); + private boolean contains(final Path path) throws IOException { + final Path cache = this.cached(path); final boolean res; - if (Files.exists(path) && time.isPresent()) { - res = Files.readAttributes(path, BasicFileAttributes.class) - .creationTime() + if (Files.exists(cache)) { + res = !Files + .getLastModifiedTime(cache) .toInstant() - .truncatedTo(ChronoUnit.MINUTES) - .equals( - ZonedDateTime.parse(time.get()).toInstant().truncatedTo(ChronoUnit.MINUTES) - ); + .isBefore( + Files.getLastModifiedTime(path) + .toInstant() + ); } else { res = false; } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptSpy.java b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptSpy.java index 3bbab94e29..df73d22c7a 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptSpy.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptSpy.java @@ -25,8 +25,10 @@ import com.jcabi.log.Logger; import com.jcabi.xml.XML; +import com.jcabi.xml.XMLDocument; import com.yegor256.xsline.Shift; import com.yegor256.xsline.Train; +import java.io.FileNotFoundException; import java.nio.file.Path; import org.eolang.maven.Place; import org.eolang.maven.SpyTrain; @@ -66,13 +68,16 @@ public OptSpy(final Train trn, final Path target) { } @Override - public XML apply(final XML xml) { - final Place place = new Place(xml.xpath("/program/@name").get(0)); - final Path dir = place.make(this.target, ""); + public XML apply(final Path path) throws FileNotFoundException { + final Path dir = new Place( + new XMLDocument(path) + .xpath("/program/@name") + .get(0)) + .make(this.target, ""); Logger.debug( this, "Optimization steps will be tracked to %s", new Rel(dir) ); - return new OptTrain(new SpyTrain(this.train, dir)).apply(xml); + return new OptTrain(new SpyTrain(this.train, dir)).apply(path); } } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptTrain.java b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptTrain.java index 0dfb18ac17..a1c5d196ac 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptTrain.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/OptTrain.java @@ -24,6 +24,7 @@ package org.eolang.maven.optimization; import com.jcabi.xml.XML; +import com.jcabi.xml.XMLDocument; import com.yegor256.xsline.Shift; import com.yegor256.xsline.StClasspath; import com.yegor256.xsline.TrClasspath; @@ -31,6 +32,8 @@ import com.yegor256.xsline.TrFast; import com.yegor256.xsline.Train; import com.yegor256.xsline.Xsline; +import java.io.FileNotFoundException; +import java.nio.file.Path; /** * Optimisation train of XLS`s. @@ -87,7 +90,7 @@ public OptTrain() { * @param shifts XLS shifts. */ public OptTrain(final Train shifts) { - this(xml -> xml, shifts); + this(path -> new XMLDocument(path), shifts); } /** @@ -117,7 +120,7 @@ public OptTrain( } @Override - public XML apply(final XML xml) { - return new Xsline(this.shifts).pass(this.delegate.apply(xml)); + public XML apply(final Path path) throws FileNotFoundException { + return new Xsline(this.shifts).pass(this.delegate.apply(path)); } } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/Optimization.java b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/Optimization.java index 78efed87ba..9fcab4f367 100644 --- a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/Optimization.java +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/Optimization.java @@ -24,6 +24,8 @@ package org.eolang.maven.optimization; import com.jcabi.xml.XML; +import java.io.FileNotFoundException; +import java.nio.file.Path; import java.util.function.Function; /** @@ -32,5 +34,20 @@ * @since 0.28.11 */ @FunctionalInterface -public interface Optimization extends Function { +public interface Optimization extends ThrowingFunction { + + /** + * Return function if it works without exception. + * + * @return The function result + */ + default Function unchecked() { + return input -> { + try { + return this.apply(input); + } catch (final FileNotFoundException exception) { + throw new PathNotFoundException(input, exception); + } + }; + } } diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/PathNotFoundException.java b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/PathNotFoundException.java new file mode 100644 index 0000000000..1fa6fe2993 --- /dev/null +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/PathNotFoundException.java @@ -0,0 +1,47 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 Objectionary.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.eolang.maven.optimization; + +import java.nio.file.Path; + +/** + * If the path isn't valid. + * @since 0.35.0 + */ +public class PathNotFoundException extends RuntimeException { + + /** + * Ctor. + * @param path The path. + * @param cause The cause. + */ + PathNotFoundException(final Path path, final Throwable cause) { + super( + String.format( + "Cannot get XML from path '%s'", path + ), + cause + ); + } +} diff --git a/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/ThrowingFunction.java b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/ThrowingFunction.java new file mode 100644 index 0000000000..ce5e774828 --- /dev/null +++ b/eo-maven-plugin/src/main/java/org/eolang/maven/optimization/ThrowingFunction.java @@ -0,0 +1,43 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016-2023 Objectionary.com + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.eolang.maven.optimization; + +/** + * Abstraction for XML optimizations. + * @param Input type. + * @param Return type. + * @param Exception type. + * @since 0.35.0 + */ +@FunctionalInterface +public interface ThrowingFunction { + /** + * Applies this function to the given argument. + * + * @param input The function argument + * @return The function result + * @throws E If fails + */ + R apply(I input) throws E; +} diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/OptimizeMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/OptimizeMojoTest.java index 7bfb64a236..0e91c5262b 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/OptimizeMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/OptimizeMojoTest.java @@ -25,8 +25,10 @@ import com.jcabi.xml.XMLDocument; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -43,7 +45,6 @@ import org.hamcrest.io.FileMatchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assumptions; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.params.ParameterizedTest; @@ -118,7 +119,6 @@ void optimizesIfExpired(@TempDir final Path temp) throws Exception { * then enable the test. * Also, see this issue. */ - @Disabled @Test void getsAlreadyOptimizedResultsFromCache(@TempDir final Path temp) throws Exception { final TextOf cached = new TextOf( @@ -132,6 +132,15 @@ void getsAlreadyOptimizedResultsFromCache(@TempDir final Path temp) throws Excep .resolve(hash) .resolve("foo/x/main.xmir") ); + Files.setLastModifiedTime( + cache.resolve( + Paths + .get(OptimizeMojo.OPTIMIZED) + .resolve(hash) + .resolve("foo/x/main.xmir") + ), + FileTime.fromMillis(System.currentTimeMillis() + 50_000) + ); new FakeMaven(temp) .withHelloWorld() .with("cache", cache) diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/ShakeMojoTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/ShakeMojoTest.java index 2cf4be61f7..55cd41a554 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/ShakeMojoTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/ShakeMojoTest.java @@ -25,8 +25,10 @@ import com.jcabi.xml.XMLDocument; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; import java.util.Map; import java.util.concurrent.TimeUnit; import org.cactoos.io.ResourceOf; @@ -37,7 +39,6 @@ import org.hamcrest.io.FileMatchers; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -82,7 +83,6 @@ void shakesSuccessfully(@TempDir final Path temp) throws IOException { ); } - @Disabled @Test void getsAlreadyShakenResultsFromCache(@TempDir final Path temp) throws Exception { final TextOf cached = new TextOf( @@ -96,6 +96,10 @@ void getsAlreadyShakenResultsFromCache(@TempDir final Path temp) throws Exceptio .resolve(hash) .resolve("foo/x/main.xmir") ); + Files.setLastModifiedTime( + cache.resolve(Paths.get(ShakeMojo.SHAKEN).resolve(hash).resolve("foo/x/main.xmir")), + FileTime.fromMillis(System.currentTimeMillis() + 50_000) + ); new FakeMaven(temp) .withHelloWorld() .with("cache", cache) diff --git a/eo-maven-plugin/src/test/java/org/eolang/maven/optimization/OptCachedTest.java b/eo-maven-plugin/src/test/java/org/eolang/maven/optimization/OptCachedTest.java index 374c8b24dd..7394231d0b 100644 --- a/eo-maven-plugin/src/test/java/org/eolang/maven/optimization/OptCachedTest.java +++ b/eo-maven-plugin/src/test/java/org/eolang/maven/optimization/OptCachedTest.java @@ -27,15 +27,14 @@ import com.jcabi.xml.XMLDocument; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; +import java.nio.file.attribute.FileTime; import org.eolang.maven.util.HmBase; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.hamcrest.io.FileMatchers; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.xembly.Directives; @@ -50,73 +49,93 @@ final class OptCachedTest { /** * Test case for XML program in cache. * - * @param tmp Temp dir + * @param cache Temp cache dir + * @param dir Temp program dir * @throws IOException if I/O fails * @todo #2422:60min returnsFromCacheIfXmlAlreadyInCache: this test is unstable. * We should resolve issues with unstable failures and only * then enable the test. * Also, see this issue. */ - @Disabled @Test - void returnsFromCacheIfXmlAlreadyInCache(@TempDir final Path tmp) throws IOException { - final XML program = OptCachedTest.program(ZonedDateTime.now()); - OptCachedTest.save(tmp, program); + void returnsFromCacheIfXmlAlreadyInCache(@TempDir final Path cache, @TempDir final Path dir) + throws IOException { + final XML xml = OptCachedTest.program(); + final FileTime time = FileTime.fromMillis(System.currentTimeMillis()); + final Path program = OptCachedTest.save(dir, xml); + OptCachedTest.setTime(dir, time); + OptCachedTest.save(cache, xml); + OptCachedTest.setTime(cache, time); MatcherAssert.assertThat( "We expected that the program will be returned from the cache.", new OptCached( path -> { throw new IllegalStateException("This code shouldn't be executed"); }, - tmp + cache ).apply(program), - Matchers.equalTo(program) + Matchers.equalTo(xml) ); } - @Disabled @Test - void returnsFromCacheButTimesSaveAndExecuteDifferent(@TempDir final Path tmp) + void returnsFromCacheButTimesSaveAndExecuteDifferent( + @TempDir final Path cache, + @TempDir final Path dir + ) throws IOException { - final XML program = OptCachedTest.program(ZonedDateTime.now().minusMinutes(2)); - OptCachedTest.save(tmp, program); + final XML xml = OptCachedTest.program(); + final Path program = OptCachedTest.save(dir, xml); + OptCachedTest.setTime( + dir, + FileTime.fromMillis(System.currentTimeMillis()) + ); + OptCachedTest.save(cache, xml); + OptCachedTest.setTime( + cache, + FileTime.fromMillis(System.currentTimeMillis() + 2000) + ); MatcherAssert.assertThat( - "We expected that the not immediately saved program will be returned from the cache.", + "We expected that the program will be returned from the cache.", new OptCached( path -> { throw new IllegalStateException("This code shouldn't be executed"); }, - tmp + cache ).apply(program), - Matchers.equalTo(program) + Matchers.equalTo(xml) ); } - @Disabled @Test - void returnsFromCacheCorrectProgram(@TempDir final Path tmp) + void returnsFromCacheCorrectProgram(@TempDir final Path cache, @TempDir final Path dir) throws IOException { - final XML prev = OptCachedTest.program(ZonedDateTime.now(), "first program"); - OptCachedTest.save(tmp, prev); - final XML current = OptCachedTest.program(ZonedDateTime.now(), "second program"); + OptCachedTest.save( + cache, + OptCachedTest.program("first program") + ); + final Path current = OptCachedTest.save( + dir, + OptCachedTest.program("second program") + ); MatcherAssert.assertThat( "Expecting current program to be compiled, but prev program was returned from cache.", new OptCached( - path -> current, - tmp + path -> OptCachedTest.program("second program"), + cache ).apply(current), - Matchers.equalTo(current) + Matchers.equalTo(OptCachedTest.program("second program")) ); } @Test - void optimizesIfXmlIsAbsentInCache(@TempDir final Path tmp) { - final XML program = OptCachedTest.program(); - final Path cache = tmp.resolve("cache"); + void optimizesIfXmlIsAbsentInCache(@TempDir final Path cache, @TempDir final Path dir) + throws IOException { + final Path program = OptCachedTest.save(dir, OptCachedTest.program()); MatcherAssert.assertThat( "We expect that the program will be created and returned as is (same instance)", - new OptCached(path -> program, cache).apply(program), - Matchers.sameInstance(program) + new OptCached(path -> OptCachedTest.program(), cache).apply(program), + Matchers.equalTo(OptCachedTest.program()) ); MatcherAssert.assertThat( "We expect that the cache saved the program after the first run", @@ -126,26 +145,30 @@ void optimizesIfXmlIsAbsentInCache(@TempDir final Path tmp) { } @Test - void optimizesBecauseCacheIsExpired(@TempDir final Path tmp) throws IOException { - final XML outdated = OptCachedTest.program(ZonedDateTime.now().minusMinutes(1)); - final XML updated = OptCachedTest.program(ZonedDateTime.now()); - OptCachedTest.save(tmp, outdated); - MatcherAssert.assertThat( - "We expected that the program will be optimized because the cache is expired", - new OptCached(path -> updated, tmp).apply(outdated), - Matchers.equalTo(updated) + void optimizesBecauseCacheIsExpired( + @TempDir final Path cache, + @TempDir final Path dir) throws IOException { + final Path program = OptCachedTest.save( + dir, + OptCachedTest.program("new program") + ); + OptCachedTest.setTime(dir, FileTime.fromMillis(System.currentTimeMillis())); + OptCachedTest.save( + cache, + OptCachedTest.program("old program") + ); + OptCachedTest.setTime( + cache, + FileTime.fromMillis(System.currentTimeMillis() - 5000) ); - } - - @Test - void optimizesIfTimeIsNotSet(@TempDir final Path tmp) throws IOException { - final XML without = OptCachedTest.program(); - final XML with = OptCachedTest.program(ZonedDateTime.now()); - OptCachedTest.save(tmp, without); MatcherAssert.assertThat( - "We expected that the program will be optimized because the cache doesn't have time", - new OptCached(path -> with, tmp).apply(without), - Matchers.equalTo(with) + "We expected that the program will be optimized because the cache is expired", + new OptCached( + path -> OptCachedTest.program("new program"), + cache + ) + .apply(program), + Matchers.equalTo(OptCachedTest.program("new program")) ); } @@ -162,6 +185,19 @@ private static Path save(final Path tmp, final XML xml) throws IOException { return res; } + /** + * Set time of XML program use absolute path of program. + * @param path Temporary test directory. + * @param time XML program. + * @return Path to saved program. + */ + private static void setTime( + final Path path, + final FileTime time) throws IOException { + final Path program = path.resolve(Paths.get("main.xmir")); + Files.setLastModifiedTime(program, time); + } + /** * Generates EO program for tests. * @return XML representation of program. @@ -177,28 +213,17 @@ private static XML program() { ); } - /** - * Generates EO program for tests with specified time. - * @param time Time. - * @return XML representation of program. - */ - private static XML program(final ZonedDateTime time) { - return OptCachedTest.program(time, "same"); - } - /** * Generates EO program for tests with specified time and context. - * @param time Time. * @param something String. * @return XML representation of program. */ - private static XML program(final ZonedDateTime time, final String something) { + private static XML program(final String something) { return new XMLDocument( new Xembler( new Directives() .add("program") .attr("name", "main") - .attr("time", time.format(DateTimeFormatter.ISO_INSTANT)) .attr("something", something) .up() ).xmlQuietly()