This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push: new 213b4abe2 RANGER-3815: added support for validity-period/access-time condition in policy-items 213b4abe2 is described below commit 213b4abe2147e58b3aa12d824519b1cd543f5c18 Author: Madhan Neethiraj <mad...@apache.org> AuthorDate: Fri Oct 27 18:23:00 2023 -0700 RANGER-3815: added support for validity-period/access-time condition in policy-items --- .../policyengine/RangerRequestScriptEvaluator.java | 31 +++ .../ranger/plugin/util/RangerCommonConstants.java | 3 + .../ranger/plugin/util/RangerTimeRangeChecker.java | 128 +++++++++ .../RangerRequestScriptEvaluatorTest.java | 29 ++ .../plugin/util/RangerTimeRangeCheckerTest.java | 291 +++++++++++++++++++++ 5 files changed, 482 insertions(+) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java index 884f69137..2c1fe2ac1 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/policyengine/RangerRequestScriptEvaluator.java @@ -28,6 +28,7 @@ import org.apache.ranger.plugin.contextenricher.RangerTagForEval; import org.apache.ranger.plugin.util.MacroProcessor; import org.apache.ranger.plugin.util.RangerAccessRequestUtil; import org.apache.ranger.plugin.util.RangerPerfTracer; +import org.apache.ranger.plugin.util.RangerTimeRangeChecker; import org.apache.ranger.plugin.util.RangerUserStore; import org.apache.ranger.plugin.util.JavaScriptEdits; import org.slf4j.Logger; @@ -839,6 +840,32 @@ public final class RangerRequestScriptEvaluator { return !userRoles.isEmpty(); } + public boolean isAccessTimeAfter(String strTime) { + return isAccessTimeBetween(strTime, null, null); + } + + public boolean isAccessTimeAfter(String strTime, String timeZone) { + return isAccessTimeBetween(strTime, null, timeZone); + } + + public boolean isAccessTimeBefore(String strTime) { + return isAccessTimeBetween(null, strTime, null); + } + + public boolean isAccessTimeBefore(String strTime, String timeZone) { + return isAccessTimeBetween(null, strTime, timeZone); + } + + public boolean isAccessTimeBetween(String fromTime, String toTime) { + return isAccessTimeBetween(fromTime, toTime, null); + } + + public boolean isAccessTimeBetween(String fromTime, String toTime, String timeZone) { + RangerTimeRangeChecker evaluator = new RangerTimeRangeChecker(fromTime, toTime, timeZone); + + return evaluator.isInRange(getAccessTime().getTime()); + } + // for backward compatibility public String ugNamesCsv() { return ugNames(null, STR_COMMA); @@ -1279,6 +1306,9 @@ public final class RangerRequestScriptEvaluator { ret.put(SCRIPT_MACRO_IS_IN_ANY_ROLE, "ctx.isInAnyRole()"); ret.put(SCRIPT_MACRO_IS_NOT_IN_ANY_GROUP, "!ctx.isInAnyGroup()"); ret.put(SCRIPT_MACRO_IS_NOT_IN_ANY_ROLE, "!ctx.isInAnyRole()"); + ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_AFTER, "ctx.isAccessTimeAfter"); + ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_BEFORE, "ctx.isAccessTimeBefore"); + ret.put(SCRIPT_MACRO_IS_ACCESS_TIME_BETWEEN, "ctx.isAccessTimeBetween"); return ret; } @@ -1363,4 +1393,5 @@ public final class RangerRequestScriptEvaluator { return ret; } } + } diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java index fa59e8d58..8081dd346 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerCommonConstants.java @@ -150,6 +150,9 @@ public class RangerCommonConstants { public static final String SCRIPT_MACRO_IS_IN_ANY_ROLE = "IS_IN_ANY_ROLE"; public static final String SCRIPT_MACRO_IS_NOT_IN_ANY_GROUP = "IS_NOT_IN_ANY_GROUP"; public static final String SCRIPT_MACRO_IS_NOT_IN_ANY_ROLE = "IS_NOT_IN_ANY_ROLE"; + public static final String SCRIPT_MACRO_IS_ACCESS_TIME_AFTER = "IS_ACCESS_TIME_AFTER"; + public static final String SCRIPT_MACRO_IS_ACCESS_TIME_BEFORE = "IS_ACCESS_TIME_BEFORE"; + public static final String SCRIPT_MACRO_IS_ACCESS_TIME_BETWEEN = "IS_ACCESS_TIME_BETWEEN"; public static final String SCRIPT_POLYFILL_INCLUDES = "if (!Array.prototype.includes) {\n" + " Object.defineProperty(\n" + diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerTimeRangeChecker.java b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerTimeRangeChecker.java new file mode 100644 index 000000000..e6e9b1528 --- /dev/null +++ b/agents-common/src/main/java/org/apache/ranger/plugin/util/RangerTimeRangeChecker.java @@ -0,0 +1,128 @@ +/* + * 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.ranger.plugin.util; + +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.TimeZone; + +public class RangerTimeRangeChecker { + private static final Logger LOG = LoggerFactory.getLogger(RangerTimeRangeChecker.class); + + private static final TimeZone DEFAULT_TIMEZONE = TimeZone.getDefault(); + private static final ThreadLocal<DateFormat> DATE_TIME_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")); + private static final ThreadLocal<DateFormat> DATE_TIME_FORMAT_2 = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy/MM/dd HH:mm")); + private static final ThreadLocal<DateFormat> DATE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy/MM/dd")); + private static final ThreadLocal<DateFormat>[] DATE_FORMATS = new ThreadLocal[] {DATE_TIME_FORMAT, DATE_TIME_FORMAT_2, DATE_FORMAT}; + + private final long fromTime; + private final long toTime; + + + public RangerTimeRangeChecker(String fromTime, String toTime, String timeZone) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> RangerTimeRangeChecker({}, {})", fromTime, toTime); + } + + TimeZone tz = StringUtils.isNotBlank(timeZone) ? TimeZone.getTimeZone(timeZone) : null;; + + this.fromTime = parseDateTime(fromTime, tz); + this.toTime = parseDateTime(toTime, tz); + + if (LOG.isDebugEnabled()) { + LOG.debug("<== RangerTimeRangeChecker({}, {}): fromTime={}, toTime={}", fromTime, toTime, this.fromTime, this.toTime); + } + } + + public boolean isInRange(long time) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> isInRange({})", time); + } + + final boolean ret; + + if (toTime < 0) { // IS_ACCESS_TIME_AFTER + ret = time > fromTime; + } else if (fromTime < 0) { // IS_ACCESS_TIME_BEFORE + ret = time < toTime; + } else { // IS_ACCESS_TIME_BETWEEN + ret = time >= fromTime && time < toTime; + } + + if (LOG.isDebugEnabled()) { + LOG.debug("<== isInRange({}): fromTime={}, toTime={} ret={}", time, fromTime, toTime, ret); + } + + return ret; + } + + private static long parseDateTime(String str, TimeZone tz) { + final long ret; + + if (StringUtils.isNotBlank(str)) { + Date date = null; + ParseException excp = null; + + for (ThreadLocal<DateFormat> formatter : DATE_FORMATS) { + try { + date = formatter.get().parse(str); + + break; + } catch (ParseException exception) { + excp = exception; + } + } + + if (date != null) { + ret = tz != null ? getAdjustedTime(date.getTime(), tz) : date.getTime(); + } else { + LOG.error("Error parsing date:[{}]", str, excp); + + ret = -1; + } + } else { + ret = -1; + } + + return ret; + } + + private static long getAdjustedTime(long localTime, TimeZone timeZone) { + final long ret; + + if (!DEFAULT_TIMEZONE.equals(timeZone)) { + int targetOffset = timeZone.getOffset(localTime); + int defaultOffset = DEFAULT_TIMEZONE.getOffset(localTime); + int diff = defaultOffset - targetOffset; + + ret = localTime + diff; + } else { + ret = localTime; + } + + return ret; + } +} diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java index 6705327d8..d3e343480 100644 --- a/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java +++ b/agents-common/src/test/java/org/apache/ranger/plugin/conditionevaluator/RangerRequestScriptEvaluatorTest.java @@ -433,6 +433,35 @@ public class RangerRequestScriptEvaluatorTest { Assert.assertNull("test: java.lang.Runtime.getRuntime().exec(\"bash\");", evaluator.evaluateScript(scriptEngine, "java.lang.Runtime.getRuntime().exec(\"bash\");")); } + @Test + public void testIsTimeMacros() { + RangerAccessRequest request = createRequest("test-user", Collections.emptySet(), Collections.emptySet(), Collections.emptyList()); + RangerRequestScriptEvaluator evaluator = new RangerRequestScriptEvaluator(request); + + // Date + Assert.assertTrue("test: IS_ACCESS_TIME_AFTER('2020/01/01')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_AFTER('2020/01/01')")); + Assert.assertTrue("test: IS_ACCESS_TIME_AFTER('2020/01/01', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_AFTER('2020/01/01', 'GMT')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BEFORE('2100/01/01')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BEFORE('2100/01/01')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BEFORE('2100/01/01', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BEFORE('2100/01/01', 'GMT')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BETWEEN('2010/01/01', '2100/01/01')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BETWEEN('2010/01/01', '2100/01/01')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BETWEEN('2010/01/01', '2100/01/01', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BETWEEN('2010/01/01', '2100/01/01', 'GMT')")); + + // Date hh:mm + Assert.assertTrue("test: IS_ACCESS_TIME_AFTER('2020/01/01 15:00')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_AFTER('2020/01/01 15:00')")); + Assert.assertTrue("test: IS_ACCESS_TIME_AFTER('2020/01/01 15:00', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_AFTER('2020/01/01 15:00', 'GMT')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BEFORE('2100/01/01 15:00')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BEFORE('2100/01/01 15:00')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BEFORE('2100/01/01 15:00', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BEFORE('2100/01/01 15:00', 'GMT')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00', '2100/01/01 15:00')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00', '2100/01/01 15:00')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00', '2100/01/01 15:00', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00', '2100/01/01 15:00', 'GMT')")); + + // Date hh:mm:ss + Assert.assertTrue("test: IS_ACCESS_TIME_AFTER('2020/01/01 15:00:42')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_AFTER('2020/01/01 15:00:42')")); + Assert.assertTrue("test: IS_ACCESS_TIME_AFTER('2020/01/01 15:00:42', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_AFTER('2020/01/01 15:00:42', 'GMT')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BEFORE('2100/01/01 15:00:42')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BEFORE('2100/01/01 15:00:42')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BEFORE('2100/01/01 15:00:42', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BEFORE('2100/01/01 15:00:42', 'GMT')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00:42', '2100/01/01 15:00:42')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00:42', '2100/01/01 15:00:42')")); + Assert.assertTrue("test: IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00:42', '2100/01/01 15:00:42', 'GMT')", (Boolean) evaluator.evaluateScript(scriptEngine, "IS_ACCESS_TIME_BETWEEN('2010/01/01 15:00:42', '2100/01/01 15:00:42', 'GMT')")); + } RangerAccessRequest createRequest(String userName, Set<String> userGroups, Set<String> userRoles, List<RangerTag> resourceTags) { RangerAccessResource resource = mock(RangerAccessResource.class); diff --git a/agents-common/src/test/java/org/apache/ranger/plugin/util/RangerTimeRangeCheckerTest.java b/agents-common/src/test/java/org/apache/ranger/plugin/util/RangerTimeRangeCheckerTest.java new file mode 100644 index 000000000..7065180ef --- /dev/null +++ b/agents-common/src/test/java/org/apache/ranger/plugin/util/RangerTimeRangeCheckerTest.java @@ -0,0 +1,291 @@ +/* + * 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.ranger.plugin.util; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.Calendar; +import java.util.TimeZone; + +public class RangerTimeRangeCheckerTest { + private static final String[] TIME_ZONES = { null, "GMT", "PDT" }; + + @Test + public void testAfterDate() { + String baseTime = "2023/06/05"; + int year = 2023, month = 6, day = 5, hour = 0, min = 0, sec = 0; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(baseTime, null, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // baseTime (should be *after*) + long time = getTime(year, month, day, hour, min, sec, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec, tz), checker.isInRange(time)); + + // baseTime + 1 second + time = getTime(year, month, day, hour, min, sec + 1, tz); + Assert.assertTrue(toDateString(year, month, day, hour, min, sec + 1, tz), checker.isInRange(time)); + + // baseTime - 1 second + time = getTime(year, month, day, hour, min, sec - 1, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testAfterDateHHMM() { + String baseTime = "2023/06/05 5:5"; + int year = 2023, month = 6, day = 5, hour = 5, min = 5, sec = 0; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(baseTime, null, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // baseTime (should be *after*) + long time = getTime(year, month, day, hour, min, sec, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec, tz), checker.isInRange(time)); + + // baseTime + 1 second + time = getTime(year, month, day, hour, min, sec + 1, tz); + Assert.assertTrue(toDateString(year, month, day, hour, min, sec + 1, tz), checker.isInRange(time)); + + // baseTime - 1 second + time = getTime(year, month, day, hour, min, sec - 1, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testAfterDateHHMMss() { + String baseTime = "2023/06/05 5:5:5"; + int year = 2023, month = 6, day = 5, hour = 5, min = 5, sec = 5; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(baseTime, null, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // baseTime (should be *after*) + long time = getTime(year, month, day, hour, min, sec, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec, tz), checker.isInRange(time)); + + // baseTime + 1 second + time = getTime(year, month, day, hour, min, sec + 1, tz); + Assert.assertTrue(toDateString(year, month, day, hour, min, sec + 1, tz), checker.isInRange(time)); + + // baseTime - 1 second + time = getTime(year, month, day, hour, min, sec - 1, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testBeforeDate() { + String baseTime = "2023/07/05"; + int year = 2023, month = 7, day = 5, hour = 0, min = 0, sec = 0; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(null, baseTime, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // baseTime (should be *before*) + long time = getTime(year, month, day, hour, min, sec, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec, tz), checker.isInRange(time)); + + // baseTime + 1 second + time = getTime(year, month, day, hour, min, sec + 1, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec + 1, tz), checker.isInRange(time)); + + // baseTime - 1 second + time = getTime(year, month, day, hour, min, sec - 1, tz); + Assert.assertTrue(toDateString(year, month, day, hour, min, sec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testBeforeDateHHMM() { + String baseTime = "2023/07/05 5:5"; + int year = 2023, month = 7, day = 5, hour = 5, min = 5, sec = 0; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(null, baseTime, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // baseTime (should be *before*) + long time = getTime(year, month, day, hour, min, sec, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec, tz), checker.isInRange(time)); + + // baseTime + 1 second + time = getTime(year, month, day, hour, min, sec + 1, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec + 1, tz), checker.isInRange(time)); + + // baseTime - 1 second + time = getTime(year, month, day, hour, min, sec - 1, tz); + Assert.assertTrue(toDateString(year, month, day, hour, min, sec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testBeforeDateHHMMss() { + String baseTime = "2023/07/05 5:5:5"; + int year = 2023, month = 7, day = 5, hour = 5, min = 5, sec = 5; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(null, baseTime, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // baseTime (should be *before*) + long time = getTime(year, month, day, hour, min, sec, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec, tz), checker.isInRange(time)); + + // baseTime + 1 second + time = getTime(year, month, day, hour, min, sec + 1, tz); + Assert.assertFalse(toDateString(year, month, day, hour, min, sec + 1, tz), checker.isInRange(time)); + + // baseTime - 1 second + time = getTime(year, month, day, hour, min, sec - 1, tz); + Assert.assertTrue(toDateString(year, month, day, hour, min, sec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testBetweenDate() { + String fromTime = "2023/06/05"; + String toTIme = "2023/07/05"; + int fromYear = 2023, fromMonth = 6, fromDay = 5, fromHour = 0, fromMin = 0, fromSec = 0; + int toYear = 2023, toMonth = 7, toDay = 5, toHour = 0, toMin = 0, toSec = 0; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(fromTime, toTIme, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // fromTime (should be *on or after*) + long time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec, tz); + Assert.assertTrue(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec, tz), checker.isInRange(time)); + + // fromTime + 1 second + time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec + 1, tz); + Assert.assertTrue(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec + 1, tz), checker.isInRange(time)); + + // fromTime - 1 second + time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec - 1, tz); + Assert.assertFalse(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec - 1, tz), checker.isInRange(time)); + + // toTime (should be *before*) + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec, tz); + Assert.assertFalse(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec, tz), checker.isInRange(time)); + + // toTime + 1 second + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec + 1, tz); + Assert.assertFalse(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec + 1, tz), checker.isInRange(time)); + + // toTime - 1 second + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec - 1, tz); + Assert.assertTrue(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testBetweenDateHHMM() { + String fromTime = "2023/06/05 5:5"; + String toTIme = "2023/07/05 5:5"; + int fromYear = 2023, fromMonth = 6, fromDay = 5, fromHour = 5, fromMin = 5, fromSec = 0; + int toYear = 2023, toMonth = 7, toDay = 5, toHour = 5, toMin = 5, toSec = 0; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(fromTime, toTIme, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // fromTime (should be *on or after*) + long time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec, tz); + Assert.assertTrue(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec, tz), checker.isInRange(time)); + + // fromTime + 1 second + time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec + 1, tz); + Assert.assertTrue(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec + 1, tz), checker.isInRange(time)); + + // fromTime - 1 second + time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec - 1, tz); + Assert.assertFalse(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec - 1, tz), checker.isInRange(time)); + + // toTime (should be *before*) + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec, tz); + Assert.assertFalse(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec, tz), checker.isInRange(time)); + + // toTime + 1 second + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec + 1, tz); + Assert.assertFalse(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec + 1, tz), checker.isInRange(time)); + + // toTime - 1 second + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec - 1, tz); + Assert.assertTrue(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec - 1, tz), checker.isInRange(time)); + } + } + + @Test + public void testBetweenDateHHMMss() { + String fromTime = "2023/06/05 5:5:5"; + String toTIme = "2023/07/05 5:5:5"; + int fromYear = 2023, fromMonth = 6, fromDay = 5, fromHour = 5, fromMin = 5, fromSec = 5; + int toYear = 2023, toMonth = 7, toDay = 5, toHour = 5, toMin = 5, toSec = 5; + + for (String timeZone : TIME_ZONES) { + RangerTimeRangeChecker checker = new RangerTimeRangeChecker(fromTime, toTIme, timeZone); + TimeZone tz = timeZone == null ? TimeZone.getDefault() : TimeZone.getTimeZone(timeZone); + + // fromTime (should be *on or after*) + long time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec, tz); + Assert.assertTrue(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec, tz), checker.isInRange(time)); + + // fromTime + 1 second + time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec + 1, tz); + Assert.assertTrue(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec + 1, tz), checker.isInRange(time)); + + // fromTime - 1 second + time = getTime(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec - 1, tz); + Assert.assertFalse(toDateString(fromYear, fromMonth, fromDay, fromHour, fromMin, fromSec - 1, tz), checker.isInRange(time)); + + // toTime (should be *before*) + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec, tz); + Assert.assertFalse(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec, tz), checker.isInRange(time)); + + // toTime + 1 second + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec + 1, tz); + Assert.assertFalse(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec + 1, tz), checker.isInRange(time)); + + // toTime - 1 second + time = getTime(toYear, toMonth, toDay, toHour, toMin, toSec - 1, tz); + Assert.assertTrue(toDateString(toYear, toMonth, toDay, toHour, toMin, toSec - 1, tz), checker.isInRange(time)); + } + } + + private long getTime(int year, int month, int day, int hour, int minute, int sec, TimeZone tz) { + Calendar cal = new Calendar.Builder().setDate(year, month - 1, day).setTimeOfDay(hour, minute, sec).setTimeZone(tz).build(); + + return cal.getTime().getTime(); + } + + private static String toDateString(int year, int month, int day, int hour, int minute, int sec, TimeZone tz) { + Calendar cal = new Calendar.Builder().setDate(year, month - 1, day).setTimeOfDay(hour, minute, sec).setTimeZone(tz).build(); + + return cal.getTime().toString(); + } +}