diff --git a/java/google/registry/tools/GenerateZoneFilesCommand.java b/java/google/registry/tools/GenerateZoneFilesCommand.java index 1e2089c6c..e9333f906 100644 --- a/java/google/registry/tools/GenerateZoneFilesCommand.java +++ b/java/google/registry/tools/GenerateZoneFilesCommand.java @@ -21,7 +21,7 @@ import static org.joda.time.Duration.standardMinutes; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.google.common.collect.ImmutableMap; -import google.registry.tools.params.DateTimeParameter; +import google.registry.tools.params.DateParameter; import google.registry.tools.server.GenerateZoneFilesAction; import java.io.IOException; import java.util.List; @@ -33,16 +33,17 @@ import org.joda.time.DateTime; final class GenerateZoneFilesCommand implements ServerSideCommand { @Parameter( - description = "A comma-separated list of TLDs to generate zone files for", + description = "One or more TLDs to generate zone files for", required = true) private List mainParameters; // Default to latest midnight that's at least 2 minutes ago. @Parameter( - names = "--export_time", - description = "The (midnight UTC) time to generate the file for (defaults to last midnight).", - validateWith = DateTimeParameter.class) - private DateTime exportTime = DateTime.now(UTC).minus(standardMinutes(2)).withTimeAtStartOfDay(); + names = "--export_date", + description = "The date to generate the file for (defaults to today, or yesterday if run " + + "before 00:02).", + validateWith = DateParameter.class) + private DateTime exportDate = DateTime.now(UTC).minus(standardMinutes(2)).withTimeAtStartOfDay(); private Connection connection; @@ -58,7 +59,7 @@ final class GenerateZoneFilesCommand implements ServerSideCommand { } ImmutableMap params = ImmutableMap.of( "tlds", mainParameters, - "exportTime", exportTime.toString()); + "exportTime", exportDate.toString()); Map response = connection.sendJson(GenerateZoneFilesAction.PATH, params); System.out.printf( "Job started at %s%s\n", diff --git a/java/google/registry/tools/params/DateParameter.java b/java/google/registry/tools/params/DateParameter.java new file mode 100644 index 000000000..1ccea8d6a --- /dev/null +++ b/java/google/registry/tools/params/DateParameter.java @@ -0,0 +1,45 @@ +// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// +// Licensed 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 google.registry.tools.params; + +import static org.joda.time.DateTimeZone.UTC; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +/** + * {@link DateTime} CLI parameter converter/validator restricted to dates. The {@link DateTime}s + * produced by this class will always have a time zone of {@link DateTimeZone#UTC}. + */ +public final class DateParameter extends ParameterConverterValidator { + + public DateParameter() { + super("not an ISO-8601 date"); + } + + /** + * Parser for DateTimes that permits only a restricted subset of ISO 8601 datetime syntax. + * The supported format is "YYYY-MM-DD", i.e. there must only be a complete date. + */ + private static final DateTimeFormatter STRICT_DATE_PARSER = + new DateTimeFormatter(null, ISODateTimeFormat.date().getParser()); + + @Override + public DateTime convert(String value) { + return DateTime.parse(value, STRICT_DATE_PARSER).withZoneRetainFields(UTC); + } +} diff --git a/javatests/google/registry/tools/params/DateParameterTest.java b/javatests/google/registry/tools/params/DateParameterTest.java new file mode 100644 index 000000000..2fbd1e757 --- /dev/null +++ b/javatests/google/registry/tools/params/DateParameterTest.java @@ -0,0 +1,100 @@ +// Copyright 2017 The Nomulus Authors. All Rights Reserved. +// +// Licensed 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 google.registry.tools.params; + +import static com.google.common.truth.Truth.assertThat; + +import google.registry.testing.ExceptionRule; +import org.joda.time.DateTime; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link DateParameter}. */ +@RunWith(JUnit4.class) +public class DateParameterTest { + + @Rule + public final ExceptionRule thrown = new ExceptionRule(); + + private final DateParameter instance = new DateParameter(); + + @Test + public void testConvert_onlyDate() throws Exception { + String exampleDate = "2014-01-01"; + assertThat(instance.convert(exampleDate)).isEqualTo(DateTime.parse("2014-01-01T00:00:00Z")); + } + + @Test + public void testConvert_numeric_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("1234"); + } + + @Test + public void testConvert_validDateAndTime_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("2014-01-01T01:02:03.004Z"); + } + + @Test + public void testConvert_invalidDate_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("2014-13-33"); + } + + @Test + public void testConvert_null_throwsException() throws Exception { + thrown.expect(NullPointerException.class); + instance.convert(null); + } + + @Test + public void testConvert_empty_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert(""); + } + + @Test + public void testConvert_sillyString_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("foo"); + } + + @Test + public void testConvert_partialDate_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("2014-01"); + } + + @Test + public void testConvert_onlyTime_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("T01:02:03"); + } + + @Test + public void testConvert_partialDateAndPartialTime_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("9T9"); + } + + @Test + public void testConvert_dateAndPartialTime_throwsException() throws Exception { + thrown.expect(IllegalArgumentException.class); + instance.convert("2014-01-01T01:02"); + } +}