| // |
| // ======================================================================== |
| // Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd. |
| // ------------------------------------------------------------------------ |
| // All rights reserved. This program and the accompanying materials |
| // are made available under the terms of the Eclipse Public License v1.0 |
| // and Apache License v2.0 which accompanies this distribution. |
| // |
| // The Eclipse Public License is available at |
| // http://www.eclipse.org/legal/epl-v10.html |
| // |
| // The Apache License v2.0 is available at |
| // http://www.opensource.org/licenses/apache2.0.php |
| // |
| // You may elect to redistribute this code under either of these licenses. |
| // ======================================================================== |
| // |
| |
| package org.eclipse.jetty.util; |
| |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.junit.Assert.assertThat; |
| |
| import java.io.File; |
| import java.io.FileReader; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.attribute.FileTime; |
| import java.time.ZoneId; |
| import java.time.ZonedDateTime; |
| import java.time.format.DateTimeFormatter; |
| import java.time.temporal.ChronoUnit; |
| import java.time.temporal.TemporalAccessor; |
| import java.util.Arrays; |
| import java.util.TimeZone; |
| import java.util.concurrent.TimeUnit; |
| |
| import org.eclipse.jetty.toolchain.test.FS; |
| import org.eclipse.jetty.toolchain.test.MavenTestingUtils; |
| import org.eclipse.jetty.util.resource.ResourceTest; |
| import org.hamcrest.Matchers; |
| import org.junit.Test; |
| |
| public class RolloverFileOutputStreamTest |
| { |
| private static ZoneId toZoneId(String timezoneId) |
| { |
| ZoneId zone = TimeZone.getTimeZone(timezoneId).toZoneId(); |
| // System.out.printf(".toZoneId(\"%s\") = [id=%s,normalized=%s]%n", timezoneId, zone.getId(), zone.normalized()); |
| return zone; |
| } |
| |
| private static ZonedDateTime toDateTime(String timendate, ZoneId zone) |
| { |
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd-hh:mm:ss.S a z") |
| .withZone(zone); |
| return ZonedDateTime.parse(timendate, formatter); |
| } |
| |
| private static String toString(TemporalAccessor date) |
| { |
| DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd-hh:mm:ss.S a z"); |
| return formatter.format(date); |
| } |
| |
| private void assertSequence(ZonedDateTime midnight, Object[][] expected) |
| { |
| ZonedDateTime nextEvent = midnight; |
| |
| for (int i = 0; i < expected.length; i++) |
| { |
| long lastMs = nextEvent.toInstant().toEpochMilli(); |
| nextEvent = nextEvent.toLocalDate().plus(1, ChronoUnit.DAYS).atStartOfDay(nextEvent.getZone()); |
| assertThat("Next Event", toString(nextEvent), is(expected[i][0])); |
| long duration = (nextEvent.toInstant().toEpochMilli() - lastMs); |
| assertThat("Duration to next event", duration, is((long) expected[i][1])); |
| } |
| } |
| |
| @Test |
| public void testMidnightRolloverCalc_PST_DST_Start() |
| { |
| ZoneId zone = toZoneId("PST"); |
| ZonedDateTime initialDate = toDateTime("2016.03.10-01:23:45.0 PM PST", zone); |
| |
| ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); |
| assertThat("Midnight", toString(midnight), is("2016.03.11-12:00:00.0 AM PST")); |
| |
| Object expected[][] = { |
| {"2016.03.12-12:00:00.0 AM PST", 86_400_000L}, |
| {"2016.03.13-12:00:00.0 AM PST", 86_400_000L}, |
| {"2016.03.14-12:00:00.0 AM PDT", 82_800_000L}, // the short day |
| {"2016.03.15-12:00:00.0 AM PDT", 86_400_000L}, |
| {"2016.03.16-12:00:00.0 AM PDT", 86_400_000L}, |
| }; |
| |
| assertSequence(midnight, expected); |
| } |
| |
| @Test |
| public void testMidnightRolloverCalc_PST_DST_End() |
| { |
| ZoneId zone = toZoneId("PST"); |
| ZonedDateTime initialDate = toDateTime("2016.11.03-11:22:33.0 AM PDT", zone); |
| |
| ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); |
| assertThat("Midnight", toString(midnight), is("2016.11.04-12:00:00.0 AM PDT")); |
| |
| Object expected[][] = { |
| {"2016.11.05-12:00:00.0 AM PDT", 86_400_000L}, |
| {"2016.11.06-12:00:00.0 AM PDT", 86_400_000L}, |
| {"2016.11.07-12:00:00.0 AM PST", 90_000_000L}, // the long day |
| {"2016.11.08-12:00:00.0 AM PST", 86_400_000L}, |
| {"2016.11.09-12:00:00.0 AM PST", 86_400_000L}, |
| }; |
| |
| assertSequence(midnight, expected); |
| } |
| |
| @Test |
| public void testMidnightRolloverCalc_Sydney_DST_Start() |
| { |
| ZoneId zone = toZoneId("Australia/Sydney"); |
| ZonedDateTime initialDate = toDateTime("2016.09.31-01:23:45.0 PM AEST", zone); |
| |
| ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); |
| assertThat("Midnight", toString(midnight), is("2016.10.01-12:00:00.0 AM AEST")); |
| |
| Object expected[][] = { |
| {"2016.10.02-12:00:00.0 AM AEST", 86_400_000L}, |
| {"2016.10.03-12:00:00.0 AM AEDT", 82_800_000L}, // the short day |
| {"2016.10.04-12:00:00.0 AM AEDT", 86_400_000L}, |
| {"2016.10.05-12:00:00.0 AM AEDT", 86_400_000L}, |
| {"2016.10.06-12:00:00.0 AM AEDT", 86_400_000L}, |
| }; |
| |
| assertSequence(midnight, expected); |
| } |
| |
| @Test |
| public void testMidnightRolloverCalc_Sydney_DST_End() |
| { |
| ZoneId zone = toZoneId("Australia/Sydney"); |
| ZonedDateTime initialDate = toDateTime("2016.04.01-11:22:33.0 AM AEDT", zone); |
| |
| ZonedDateTime midnight = RolloverFileOutputStream.toMidnight(initialDate); |
| assertThat("Midnight", toString(midnight), is("2016.04.02-12:00:00.0 AM AEDT")); |
| |
| Object expected[][] = { |
| {"2016.04.03-12:00:00.0 AM AEDT", 86_400_000L}, |
| {"2016.04.04-12:00:00.0 AM AEST", 90_000_000L}, // The long day |
| {"2016.04.05-12:00:00.0 AM AEST", 86_400_000L}, |
| {"2016.04.06-12:00:00.0 AM AEST", 86_400_000L}, |
| {"2016.04.07-12:00:00.0 AM AEST", 86_400_000L}, |
| }; |
| |
| assertSequence(midnight, expected); |
| } |
| |
| @Test |
| public void testFilehandling() throws Exception |
| { |
| File testDir = MavenTestingUtils.getTargetTestingDir(ResourceTest.class.getName()); |
| Path testPath = testDir.toPath(); |
| FS.ensureEmpty(testDir); |
| |
| ZoneId zone = toZoneId("Australia/Sydney"); |
| ZonedDateTime now = toDateTime("2016.04.10-08:30:12.3 AM AEDT", zone); |
| |
| File template = new File(testDir,"test-rofos-yyyy_mm_dd.log"); |
| |
| try (RolloverFileOutputStream rofos = |
| new RolloverFileOutputStream(template.getAbsolutePath(),false,3,TimeZone.getTimeZone(zone),null,null,now)) |
| { |
| rofos.write("TICK".getBytes()); |
| rofos.flush(); |
| } |
| |
| now = now.plus(5,ChronoUnit.MINUTES); |
| |
| try (RolloverFileOutputStream rofos = |
| new RolloverFileOutputStream(template.getAbsolutePath(),false,3,TimeZone.getTimeZone(zone),null,null,now)) |
| { |
| rofos.write("TOCK".getBytes()); |
| rofos.flush(); |
| String[] ls = testDir.list(); |
| assertThat(ls.length,is(2)); |
| String backup = null; |
| for (String n: ls) |
| { |
| if (!"test-rofos-2016_04_10.log".equals(n)) |
| backup = n; |
| } |
| |
| assertThat(Arrays.asList(ls),Matchers.containsInAnyOrder(backup,"test-rofos-2016_04_10.log")); |
| |
| Files.setLastModifiedTime(testPath.resolve(backup),FileTime.from(now.toInstant())); |
| Files.setLastModifiedTime(testPath.resolve("test-rofos-2016_04_10.log"),FileTime.from(now.toInstant())); |
| |
| ZonedDateTime time = now.minus(1,ChronoUnit.DAYS); |
| for (int i=10;i-->5;) |
| { |
| String file = "test-rofos-2016_04_0"+i+".log"; |
| Path path = testPath.resolve(file); |
| FS.touch(path); |
| Files.setLastModifiedTime(path,FileTime.from(time.toInstant())); |
| |
| if (i%2==0) |
| { |
| file = "test-rofos-2016_04_0"+i+".log.083512300"; |
| path = testPath.resolve(file); |
| FS.touch(path); |
| Files.setLastModifiedTime(path,FileTime.from(time.toInstant())); |
| time = time.minus(1,ChronoUnit.DAYS); |
| } |
| |
| file = "unrelated-"+i; |
| path = testPath.resolve(file); |
| FS.touch(path); |
| Files.setLastModifiedTime(path,FileTime.from(time.toInstant())); |
| |
| time = time.minus(1,ChronoUnit.DAYS); |
| } |
| |
| ls = testDir.list(); |
| assertThat(ls.length,is(14)); |
| assertThat(Arrays.asList(ls),Matchers.containsInAnyOrder( |
| "test-rofos-2016_04_05.log", |
| "test-rofos-2016_04_06.log", |
| "test-rofos-2016_04_07.log", |
| "test-rofos-2016_04_08.log", |
| "test-rofos-2016_04_09.log", |
| "test-rofos-2016_04_10.log", |
| "test-rofos-2016_04_06.log.083512300", |
| "test-rofos-2016_04_08.log.083512300", |
| "test-rofos-2016_04_10.log.083512300", |
| "unrelated-9", |
| "unrelated-8", |
| "unrelated-7", |
| "unrelated-6", |
| "unrelated-5" |
| )); |
| |
| rofos.removeOldFiles(now); |
| ls = testDir.list(); |
| assertThat(ls.length,is(10)); |
| assertThat(Arrays.asList(ls),Matchers.containsInAnyOrder( |
| "test-rofos-2016_04_08.log", |
| "test-rofos-2016_04_09.log", |
| "test-rofos-2016_04_10.log", |
| "test-rofos-2016_04_08.log.083512300", |
| "test-rofos-2016_04_10.log.083512300", |
| "unrelated-9", |
| "unrelated-8", |
| "unrelated-7", |
| "unrelated-6", |
| "unrelated-5")); |
| |
| |
| assertThat(IO.toString(new FileReader(new File(testDir,backup))),is("TICK")); |
| assertThat(IO.toString(new FileReader(new File(testDir,"test-rofos-2016_04_10.log"))),is("TOCK")); |
| |
| } |
| } |
| |
| @Test |
| public void testRollover() throws Exception |
| { |
| File testDir = MavenTestingUtils.getTargetTestingDir(ResourceTest.class.getName()); |
| FS.ensureEmpty(testDir); |
| |
| ZoneId zone = toZoneId("Australia/Sydney"); |
| ZonedDateTime now = toDateTime("2016.04.10-11:59:55.0 PM AEDT", zone); |
| |
| File template = new File(testDir,"test-rofos-yyyy_mm_dd.log"); |
| |
| try (RolloverFileOutputStream rofos = |
| new RolloverFileOutputStream(template.getAbsolutePath(),false,0,TimeZone.getTimeZone(zone),null,null,now)) |
| { |
| rofos.write("BEFORE".getBytes()); |
| rofos.flush(); |
| String[] ls = testDir.list(); |
| assertThat(ls.length,is(1)); |
| assertThat(ls[0],is("test-rofos-2016_04_10.log")); |
| |
| TimeUnit.SECONDS.sleep(10); |
| rofos.write("AFTER".getBytes()); |
| ls = testDir.list(); |
| assertThat(ls.length,is(2)); |
| |
| for (String n : ls) |
| { |
| String content = IO.toString(new FileReader(new File(testDir,n))); |
| if ("test-rofos-2016_04_10.log".equals(n)) |
| { |
| assertThat(content,is("BEFORE")); |
| } |
| else |
| { |
| assertThat(content,is("AFTER")); |
| } |
| } |
| } |
| } |
| } |