├── .gitignore ├── CONTRIBUTING ├── LICENSE ├── README.md ├── android ├── .bazelrc ├── WORKSPACE ├── android.bazelproject ├── java │ └── com │ │ └── google │ │ └── time │ │ └── client │ │ ├── base │ │ ├── AndroidDateTimeUtils.java │ │ ├── AndroidTicker.java │ │ ├── BUILD.bazel │ │ ├── DateTimeException.java │ │ ├── Duration.java │ │ ├── Instant.java │ │ ├── InstantSource.java │ │ ├── Logger.java │ │ ├── Network.java │ │ ├── NetworkOperationResult.java │ │ ├── PlatformInstantSource.java │ │ ├── PlatformNetwork.java │ │ ├── PlatformTicker.java │ │ ├── ServerAddress.java │ │ ├── Supplier.java │ │ ├── Ticker.java │ │ ├── Ticks.java │ │ ├── annotations │ │ │ ├── NonFinalForTesting.java │ │ │ └── VisibleForTesting.java │ │ ├── impl │ │ │ ├── ClusteredServiceOperation.java │ │ │ ├── DateTimeConstants.java │ │ │ ├── ExactMath.java │ │ │ ├── NoOpLogger.java │ │ │ ├── Objects.java │ │ │ ├── PlatformRandom.java │ │ │ └── SystemStreamLogger.java │ │ └── testing │ │ │ ├── Advanceable.java │ │ │ ├── BUILD.bazel │ │ │ ├── Bytes.java │ │ │ ├── DateTimeUtils.java │ │ │ ├── FakeClocks.java │ │ │ ├── FakeInstantSource.java │ │ │ ├── FakeTicker.java │ │ │ ├── MoreAsserts.java │ │ │ ├── PredictableRandom.java │ │ │ └── TestEnvironmentUtils.java │ │ └── sntp │ │ ├── BUILD.bazel │ │ ├── BasicSntpClient.java │ │ ├── InvalidNtpValueException.java │ │ ├── NtpProtocolException.java │ │ ├── NtpServerNotReachableException.java │ │ ├── SntpClient.java │ │ ├── SntpQueryDebugInfo.java │ │ ├── SntpQueryResult.java │ │ ├── SntpTimeSignal.java │ │ ├── impl │ │ ├── Duration64.java │ │ ├── NtpDateTimeUtils.java │ │ ├── NtpHeader.java │ │ ├── NtpMessage.java │ │ ├── SerializationUtils.java │ │ ├── SntpClientEngine.java │ │ ├── SntpQueryOperation.java │ │ ├── SntpRequestFactory.java │ │ ├── SntpServiceConnector.java │ │ ├── SntpServiceConnectorImpl.java │ │ ├── SntpTimeSignalImpl.java │ │ └── Timestamp64.java │ │ └── testing │ │ ├── BUILD.bazel │ │ ├── FakeNetwork.java │ │ ├── FakeSntpServerEngine.java │ │ ├── SntpTestServer.java │ │ ├── TestSntpServerEngine.java │ │ └── TestSntpServerWithNetwork.java ├── javatests │ └── com │ │ └── google │ │ └── time │ │ └── client │ │ ├── base │ │ ├── AndroidDateTimeUtilsTest.java │ │ ├── AndroidManifest.xml │ │ ├── AndroidTestManifest.xml │ │ ├── BUILD.bazel │ │ ├── DurationTest.java │ │ ├── InstantTest.java │ │ ├── NetworkOperationResultTest.java │ │ ├── PlatformInstantSourceTest.java │ │ ├── PlatformNetworkTest.java │ │ ├── PlatformTickerTest.java │ │ ├── TickerTest.java │ │ ├── TicksTest.java │ │ ├── impl │ │ │ ├── ClusteredServiceOperationTest.java │ │ │ ├── ObjectsTest.java │ │ │ └── PlatformRandomTest.java │ │ └── testing │ │ │ ├── AndroidManifest.xml │ │ │ ├── AndroidTestManifest.xml │ │ │ ├── BUILD.bazel │ │ │ ├── BytesTest.java │ │ │ ├── DateTimeUtilsTest.java │ │ │ ├── FakeClocksTest.java │ │ │ ├── FakeTickerTest.java │ │ │ └── PredictableRandomTest.java │ │ └── sntp │ │ ├── AndroidManifest.xml │ │ ├── AndroidTestManifest.xml │ │ ├── BUILD.bazel │ │ ├── BasicSntpClientTest.java │ │ ├── SntpQueryDebugInfoTest.java │ │ ├── SntpQueryResultTest.java │ │ └── impl │ │ ├── Duration64Test.java │ │ ├── NtpDateTimeUtilsTest.java │ │ ├── NtpHeaderTest.java │ │ ├── NtpMessageTest.java │ │ ├── SerializationUtilsTest.java │ │ ├── SntpClientEngineNetworkingTest.java │ │ ├── SntpClientEngineUnitTest.java │ │ ├── SntpQueryOperationFailureResultTest.java │ │ ├── SntpQueryOperationSuccessResultTest.java │ │ ├── SntpQueryOperationTest.java │ │ ├── SntpRequestFactoryTest.java │ │ ├── SntpTimeSignalImplTest.java │ │ └── Timestamp64Test.java └── run_device_tests.sh ├── before-upload.sh ├── check-for-dupes-of-common.sh ├── common ├── java │ └── com │ │ └── google │ │ └── time │ │ └── client │ │ ├── base │ │ ├── DateTimeException.java │ │ ├── InstantSource.java │ │ ├── Logger.java │ │ ├── Network.java │ │ ├── NetworkOperationResult.java │ │ ├── PlatformInstantSource.java │ │ ├── PlatformNetwork.java │ │ ├── ServerAddress.java │ │ ├── Supplier.java │ │ ├── Ticker.java │ │ ├── Ticks.java │ │ ├── annotations │ │ │ ├── NonFinalForTesting.java │ │ │ └── VisibleForTesting.java │ │ ├── impl │ │ │ ├── ClusteredServiceOperation.java │ │ │ ├── DateTimeConstants.java │ │ │ ├── ExactMath.java │ │ │ ├── NoOpLogger.java │ │ │ ├── Objects.java │ │ │ └── SystemStreamLogger.java │ │ └── testing │ │ │ ├── Advanceable.java │ │ │ ├── Bytes.java │ │ │ ├── DateTimeUtils.java │ │ │ ├── FakeClocks.java │ │ │ ├── FakeInstantSource.java │ │ │ ├── MoreAsserts.java │ │ │ └── PredictableRandom.java │ │ └── sntp │ │ ├── BasicSntpClient.java │ │ ├── InvalidNtpValueException.java │ │ ├── NtpProtocolException.java │ │ ├── NtpServerNotReachableException.java │ │ ├── SntpClient.java │ │ ├── SntpQueryDebugInfo.java │ │ ├── SntpQueryResult.java │ │ ├── SntpTimeSignal.java │ │ ├── impl │ │ ├── Duration64.java │ │ ├── NtpDateTimeUtils.java │ │ ├── NtpHeader.java │ │ ├── NtpMessage.java │ │ ├── SerializationUtils.java │ │ ├── SntpClientEngine.java │ │ ├── SntpQueryOperation.java │ │ ├── SntpRequestFactory.java │ │ ├── SntpServiceConnector.java │ │ ├── SntpServiceConnectorImpl.java │ │ ├── SntpTimeSignalImpl.java │ │ └── Timestamp64.java │ │ └── testing │ │ ├── FakeNetwork.java │ │ ├── FakeSntpServerEngine.java │ │ ├── SntpTestServer.java │ │ ├── TestSntpServerEngine.java │ │ └── TestSntpServerWithNetwork.java └── javatests │ └── com │ └── google │ └── time │ └── client │ ├── base │ ├── DurationTest.java │ ├── InstantTest.java │ ├── NetworkOperationResultTest.java │ ├── PlatformInstantSourceTest.java │ ├── PlatformNetworkTest.java │ ├── TickerTest.java │ ├── TicksTest.java │ ├── impl │ │ ├── ClusteredServiceOperationTest.java │ │ ├── ObjectsTest.java │ │ └── PlatformRandomTest.java │ └── testing │ │ ├── BytesTest.java │ │ ├── DateTimeUtilsTest.java │ │ ├── FakeClocksTest.java │ │ └── PredictableRandomTest.java │ └── sntp │ ├── BasicSntpClientTest.java │ ├── SntpQueryDebugInfoTest.java │ ├── SntpQueryResultTest.java │ └── impl │ ├── Duration64Test.java │ ├── NtpDateTimeUtilsTest.java │ ├── NtpHeaderTest.java │ ├── NtpMessageTest.java │ ├── SerializationUtilsTest.java │ ├── SntpClientEngineNetworkingTest.java │ ├── SntpClientEngineUnitTest.java │ ├── SntpQueryOperationFailureResultTest.java │ ├── SntpQueryOperationSuccessResultTest.java │ ├── SntpQueryOperationTest.java │ ├── SntpRequestFactoryTest.java │ ├── SntpTimeSignalImplTest.java │ └── Timestamp64Test.java ├── java-time-client.bazelrc ├── java-time-client.config_template ├── javase ├── .bazelrc ├── WORKSPACE ├── java │ └── com │ │ └── google │ │ └── time │ │ └── client │ │ ├── base │ │ ├── BUILD.bazel │ │ ├── DateTimeException.java │ │ ├── Duration.java │ │ ├── Instant.java │ │ ├── InstantSource.java │ │ ├── Logger.java │ │ ├── Network.java │ │ ├── NetworkOperationResult.java │ │ ├── PlatformInstantSource.java │ │ ├── PlatformNetwork.java │ │ ├── PlatformTicker.java │ │ ├── ServerAddress.java │ │ ├── Supplier.java │ │ ├── Ticker.java │ │ ├── Ticks.java │ │ ├── annotations │ │ │ ├── NonFinalForTesting.java │ │ │ └── VisibleForTesting.java │ │ ├── impl │ │ │ ├── ClusteredServiceOperation.java │ │ │ ├── DateTimeConstants.java │ │ │ ├── ExactMath.java │ │ │ ├── NoOpLogger.java │ │ │ ├── Objects.java │ │ │ ├── PlatformRandom.java │ │ │ └── SystemStreamLogger.java │ │ └── testing │ │ │ ├── Advanceable.java │ │ │ ├── BUILD.bazel │ │ │ ├── Bytes.java │ │ │ ├── DateTimeUtils.java │ │ │ ├── FakeClocks.java │ │ │ ├── FakeInstantSource.java │ │ │ ├── FakeTicker.java │ │ │ ├── MoreAsserts.java │ │ │ ├── PredictableRandom.java │ │ │ └── TestEnvironmentUtils.java │ │ └── sntp │ │ ├── BUILD.bazel │ │ ├── BasicSntpClient.java │ │ ├── InvalidNtpValueException.java │ │ ├── NtpProtocolException.java │ │ ├── NtpServerNotReachableException.java │ │ ├── SntpClient.java │ │ ├── SntpQueryDebugInfo.java │ │ ├── SntpQueryResult.java │ │ ├── SntpTimeSignal.java │ │ ├── impl │ │ ├── Duration64.java │ │ ├── NtpDateTimeUtils.java │ │ ├── NtpHeader.java │ │ ├── NtpMessage.java │ │ ├── SerializationUtils.java │ │ ├── SntpClientEngine.java │ │ ├── SntpQueryOperation.java │ │ ├── SntpRequestFactory.java │ │ ├── SntpServiceConnector.java │ │ ├── SntpServiceConnectorImpl.java │ │ ├── SntpTimeSignalImpl.java │ │ └── Timestamp64.java │ │ ├── testing │ │ ├── BUILD.bazel │ │ ├── FakeNetwork.java │ │ ├── FakeSntpServerEngine.java │ │ ├── SntpTestServer.java │ │ ├── TestSntpServerEngine.java │ │ └── TestSntpServerWithNetwork.java │ │ └── tools │ │ ├── BUILD.bazel │ │ ├── SntpComparisonTool.java │ │ └── SntpTool.java ├── javase.bazelproject └── javatests │ └── com │ └── google │ └── time │ └── client │ ├── base │ ├── BUILD.bazel │ ├── DurationTest.java │ ├── InstantTest.java │ ├── NetworkOperationResultTest.java │ ├── PlatformInstantSourceTest.java │ ├── PlatformNetworkTest.java │ ├── PlatformTickerTest.java │ ├── TickerTest.java │ ├── TicksTest.java │ ├── impl │ │ ├── ClusteredServiceOperationTest.java │ │ ├── ObjectsTest.java │ │ └── PlatformRandomTest.java │ └── testing │ │ ├── BUILD.bazel │ │ ├── BytesTest.java │ │ ├── DateTimeUtilsTest.java │ │ ├── FakeClocksTest.java │ │ └── PredictableRandomTest.java │ └── sntp │ ├── BUILD.bazel │ ├── BasicSntpClientTest.java │ ├── SntpQueryDebugInfoTest.java │ ├── SntpQueryResultTest.java │ └── impl │ ├── Duration64Test.java │ ├── NtpDateTimeUtilsTest.java │ ├── NtpHeaderTest.java │ ├── NtpMessageTest.java │ ├── SerializationUtilsTest.java │ ├── SntpClientEngineNetworkingTest.java │ ├── SntpClientEngineUnitTest.java │ ├── SntpQueryOperationFailureResultTest.java │ ├── SntpQueryOperationSuccessResultTest.java │ ├── SntpQueryOperationTest.java │ ├── SntpRequestFactoryTest.java │ ├── SntpTimeSignalImplTest.java │ └── Timestamp64Test.java ├── reformat-java.sh ├── regenerate-common-symlinks.sh ├── replace-symlinks-to-common-with-copies.sh └── rm-copies-of-common.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | \#*\# 3 | 4 | .classpath 5 | .factorypath 6 | .project 7 | .settings 8 | eclipsebin 9 | 10 | bin 11 | gen 12 | build 13 | out 14 | #lib 15 | 16 | target 17 | pom.xml.* 18 | release.properties 19 | build.log 20 | 21 | .idea 22 | *.iml 23 | .ijwb 24 | classes 25 | 26 | obj 27 | 28 | .DS_Store 29 | 30 | dependency-reduced-pom.xml 31 | 32 | gen-external-apklibs 33 | 34 | bazel-* 35 | 36 | *.pyc 37 | 38 | .gradle 39 | 40 | java-time-client.config 41 | -------------------------------------------------------------------------------- /CONTRIBUTING: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement. You (or your employer) retain the copyright to your contribution; 10 | this simply gives us permission to use and redistribute your contributions as 11 | part of the project. Head over to to see 12 | your current agreements on file or to sign a new one. 13 | 14 | You generally only need to submit a CLA once, so if you've already submitted one 15 | (even if it was for a different project), you probably don't need to do it 16 | again. 17 | 18 | ## Code Reviews 19 | 20 | All submissions, including submissions by project members, require review. We 21 | use GitHub pull requests for this purpose. Consult 22 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 23 | information on using pull requests. 24 | 25 | ## Community Guidelines 26 | 27 | This project follows [Google's Open Source Community 28 | Guidelines](https://opensource.google/conduct/). 29 | -------------------------------------------------------------------------------- /android/.bazelrc: -------------------------------------------------------------------------------- 1 | # Include debug info in the compiled jars 2 | build --javacopt=-g 3 | build --host_javacopt=-g 4 | -------------------------------------------------------------------------------- /android/WORKSPACE: -------------------------------------------------------------------------------- 1 | # Use the Android SDK pointed to by ${ANDROID_HOME} 2 | android_sdk_repository( 3 | name = "androidsdk", 4 | api_level = 26, 5 | # This version is needed for dx, which is used by bazel android_ rules. 6 | build_tools_version = "30.0.3", 7 | ) 8 | 9 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 10 | 11 | # BEGIN Required for android_local_test 12 | http_archive( 13 | name = "robolectric", 14 | sha256 = "97f169d39f19412bdd07fd6c274dcda0a7c8f623f7f00aa5a3b94994fc6f0ec4", 15 | strip_prefix = "robolectric-bazel-4.7.3", 16 | urls = ["https://github.com/robolectric/robolectric-bazel/archive/4.7.3.tar.gz"], 17 | ) 18 | 19 | load("@robolectric//bazel:robolectric.bzl", "robolectric_repositories") 20 | 21 | robolectric_repositories() 22 | 23 | http_archive( 24 | name = "rules_jvm_external", 25 | sha256 = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca", 26 | strip_prefix = "rules_jvm_external-4.2", 27 | url = "https://github.com/bazelbuild/rules_jvm_external/archive/4.2.zip", 28 | ) 29 | 30 | load("@rules_jvm_external//:defs.bzl", "maven_install") 31 | 32 | maven_install( 33 | artifacts = [ 34 | # Robolectric 35 | "org.robolectric:robolectric:4.7.3", 36 | # Truth (for tests) 37 | "com.google.truth:truth:1.1.3", 38 | # Mockito (for tests) 39 | "org.mockito:mockito-android:jar:3.0.0", 40 | "org.mockito:mockito-core:jar:3.0.0", 41 | # Android annotation support 42 | "androidx.annotation:annotation:aar:1.3.0", 43 | # Android test suppport 44 | "junit:junit:4.13.2", 45 | "androidx.test:core:aar:1.4.0", 46 | "androidx.test:rules:aar:1.4.0", 47 | "androidx.test:runner:aar:1.4.0", 48 | ], 49 | repositories = [ 50 | "https://maven.google.com", 51 | "https://repo1.maven.org/maven2", 52 | ], 53 | ) 54 | # END Required for android_local_test 55 | 56 | # BEGIN bazel-common imports 57 | http_archive( 58 | name = "google_bazel_common", 59 | sha256 = "d8aa0ef609248c2a494d5dbdd4c89ef2a527a97c5a87687e5a218eb0b77ff640", 60 | strip_prefix = "bazel-common-4a8d451e57fb7e1efecbf9495587a10684a19eb2", 61 | urls = ["https://github.com/google/bazel-common/archive/4a8d451e57fb7e1efecbf9495587a10684a19eb2.zip"], 62 | ) 63 | # END bazel-common imports 64 | 65 | # BEGIN Android Test Support 66 | ATS_COMMIT = "d3903f728108c878308a416daa8b993c7e4c3c8e" 67 | 68 | http_archive( 69 | name = "android_test_support", 70 | sha256 = "ee3a02f269aceded11eca7055b607d35c861d87a7ea69b8d4326e34be1448a4f", 71 | strip_prefix = "android-test-%s" % ATS_COMMIT, 72 | urls = ["https://github.com/android/android-test/archive/%s.tar.gz" % ATS_COMMIT], 73 | ) 74 | 75 | load("@android_test_support//:repo.bzl", "android_test_repositories") 76 | 77 | android_test_repositories() 78 | # END Android Test Support 79 | -------------------------------------------------------------------------------- /android/android.bazelproject: -------------------------------------------------------------------------------- 1 | directories: 2 | java 3 | javatests 4 | targets: 5 | //java/com/google/time/client/... 6 | //javatests/com/google/time/client/... 7 | workspace_type: java 8 | additional_languages: 9 | android 10 | java_language_level: 8 11 | test_sources: 12 | javatests/* 13 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/AndroidDateTimeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import com.google.time.client.base.impl.DateTimeConstants; 20 | 21 | /** Utility date / time methods to support Android-specific implementations of class. */ 22 | class AndroidDateTimeUtils { 23 | 24 | private AndroidDateTimeUtils() {} 25 | 26 | /** 27 | * Checks that the supplied value falls in the range [0..999,999,999] and returns it. 28 | * 29 | * @throws DateTimeException if the value is outside of the allowed range 30 | */ 31 | public static int checkPositiveSubSecondNanos(int nanosOfSecond) { 32 | if (nanosOfSecond < 0) { 33 | throw new DateTimeException("nanosOfSecond must not be negative, is " + nanosOfSecond); 34 | } else if (nanosOfSecond >= DateTimeConstants.NANOS_PER_SECOND) { 35 | throw new DateTimeException( 36 | "nanosOfSecond must not be > " 37 | + DateTimeConstants.NANOS_PER_SECOND 38 | + ", is " 39 | + nanosOfSecond); 40 | } 41 | return nanosOfSecond; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/BUILD.bazel: -------------------------------------------------------------------------------- 1 | android_library( 2 | name = "base", 3 | srcs = glob([ 4 | "*.java", 5 | "annotations/*.java", 6 | "impl/*.java", 7 | ]), 8 | visibility = ["//visibility:public"], 9 | deps = ["@maven//:androidx_annotation_annotation"], 10 | ) 11 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/DateTimeException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/DateTimeException.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/InstantSource.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/InstantSource.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/Logger.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Logger.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/Network.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Network.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/NetworkOperationResult.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/NetworkOperationResult.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/PlatformInstantSource.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/PlatformInstantSource.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/PlatformNetwork.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/PlatformNetwork.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/PlatformTicker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_MILLISECOND; 20 | 21 | import android.os.SystemClock; 22 | import com.google.time.client.base.impl.ExactMath; 23 | 24 | /** 25 | * A {@link Ticker} that provides nanosecond-precision access to the Android kernel's CLOCK_BOOTTIME 26 | * clock. 27 | */ 28 | public final class PlatformTicker extends AndroidTicker { 29 | 30 | private static final PlatformTicker INSTANCE = new PlatformTicker(); 31 | 32 | public static AndroidTicker instance() { 33 | return INSTANCE; 34 | } 35 | 36 | private PlatformTicker() {} 37 | 38 | @Override 39 | public Ticks ticks() { 40 | return createTicks(SystemClock.elapsedRealtimeNanos()); 41 | } 42 | 43 | @Override 44 | public Ticks ticksForElapsedRealtimeNanos(long elapsedRealtimeNanos) { 45 | // This ticker uses the SystemClock.elapsedRealtimeNanos() value with no adjustments. 46 | return createTicks(elapsedRealtimeNanos); 47 | } 48 | 49 | @Override 50 | public Ticks ticksForElapsedRealtimeMillis(long elapsedRealtimeMillis) { 51 | long nanosValue = ExactMath.multiplyExact(elapsedRealtimeMillis, NANOS_PER_MILLISECOND); 52 | return createTicks(nanosValue); 53 | } 54 | 55 | @Override 56 | public long elapsedRealtimeNanosForTicks(Ticks ticks) { 57 | checkThisIsTicksOrigin(ticks); 58 | return ticks.getValue(); 59 | } 60 | 61 | @Override 62 | public long elapsedRealtimeMillisForTicks(Ticks ticks) { 63 | checkThisIsTicksOrigin(ticks); 64 | return ticks.getValue() / NANOS_PER_MILLISECOND; 65 | } 66 | 67 | @Override 68 | public Duration durationBetween(Ticks start, Ticks end) { 69 | return Duration.ofNanos(incrementsBetween(start, end)); 70 | } 71 | 72 | @Override 73 | public String toString() { 74 | return "PlatformTicker"; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/ServerAddress.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/ServerAddress.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/Supplier.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Supplier.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/Ticker.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Ticker.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/Ticks.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Ticks.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/annotations/NonFinalForTesting.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/annotations/NonFinalForTesting.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/annotations/VisibleForTesting.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/annotations/VisibleForTesting.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/ClusteredServiceOperation.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/ClusteredServiceOperation.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/DateTimeConstants.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/DateTimeConstants.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/ExactMath.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/ExactMath.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/NoOpLogger.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/NoOpLogger.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/Objects.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/Objects.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/PlatformRandom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import java.util.Random; 20 | 21 | /** Provides access to a generally suitable default {@link Random} instance. */ 22 | public final class PlatformRandom { 23 | 24 | private static final Random DEFAULT_INSTANCE = new Random(System.nanoTime()); 25 | 26 | private PlatformRandom() {} 27 | 28 | public static Random getDefaultRandom() { 29 | return DEFAULT_INSTANCE; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/impl/SystemStreamLogger.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/SystemStreamLogger.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/Advanceable.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/Advanceable.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/BUILD.bazel: -------------------------------------------------------------------------------- 1 | android_library( 2 | name = "testing", 3 | testonly = 1, 4 | srcs = glob(["*.java"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//java/com/google/time/client/base", 8 | "@maven//:junit_junit", 9 | ], 10 | ) 11 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/Bytes.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/Bytes.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/DateTimeUtils.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/FakeClocks.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/FakeClocks.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/FakeInstantSource.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/FakeInstantSource.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/FakeTicker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.base.testing; 17 | 18 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_MILLISECOND; 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.time.client.base.AndroidTicker; 22 | import com.google.time.client.base.Duration; 23 | import com.google.time.client.base.Ticker; 24 | import com.google.time.client.base.Ticks; 25 | import com.google.time.client.base.impl.ExactMath; 26 | import com.google.time.client.base.impl.Objects; 27 | 28 | /** 29 | * A fake {@link Ticker} that can be used for tests. See {@link FakeClocks} for how to obtain an 30 | * instance. This ticker simulates one that increments the tick value every nanosecond. 31 | */ 32 | public final class FakeTicker extends AndroidTicker implements Advanceable { 33 | 34 | private final FakeClocks fakeClocks; 35 | 36 | private long ticksValue; 37 | 38 | FakeTicker(FakeClocks fakeClocks) { 39 | this.fakeClocks = Objects.requireNonNull(fakeClocks); 40 | } 41 | 42 | @Override 43 | public Duration durationBetween(Ticks start, Ticks end) throws IllegalArgumentException { 44 | return Duration.ofNanos(incrementsBetween(start, end)); 45 | } 46 | 47 | @Override 48 | public Ticks ticks() { 49 | ticksValue += fakeClocks.autoAdvanceDuration.toNanos(); 50 | return getCurrentTicks(); 51 | } 52 | 53 | @Override 54 | public Ticks ticksForElapsedRealtimeNanos(long elapsedRealtimeNanos) { 55 | return ticksForValue(elapsedRealtimeNanos); 56 | } 57 | 58 | @Override 59 | public Ticks ticksForElapsedRealtimeMillis(long elapsedRealtimeMillis) { 60 | long elapsedRealtimeNanos = 61 | ExactMath.multiplyExact(elapsedRealtimeMillis, NANOS_PER_MILLISECOND); 62 | return createTicks(elapsedRealtimeNanos); 63 | } 64 | 65 | @Override 66 | public long elapsedRealtimeNanosForTicks(Ticks ticks) { 67 | checkThisIsTicksOrigin(ticks); 68 | return valueForTicks(ticks); 69 | } 70 | 71 | @Override 72 | public long elapsedRealtimeMillisForTicks(Ticks ticks) { 73 | checkThisIsTicksOrigin(ticks); 74 | return valueForTicks(ticks) / NANOS_PER_MILLISECOND; 75 | } 76 | 77 | /** Asserts the current ticks value matches the one supplied. Does not auto advance. */ 78 | public void assertCurrentTicks(Ticks actual) { 79 | assertEquals(createTicks(ticksValue), actual); 80 | } 81 | 82 | /** Returns the current ticks value. Does not auto advance. */ 83 | public Ticks getCurrentTicks() { 84 | return createTicks(ticksValue); 85 | } 86 | 87 | /** Returns a ticks value. Does not auto advance. */ 88 | public Ticks ticksForValue(long value) { 89 | return createTicks(value); 90 | } 91 | 92 | /** Sets the current ticks value. Does not auto advance. */ 93 | public void setTicksValue(long ticksValue) { 94 | this.ticksValue = ticksValue; 95 | } 96 | 97 | public void advanceNanos(long nanos) { 98 | // FakeTicker.ticksValue is fixed to nanoseconds. 99 | ticksValue += nanos; 100 | } 101 | 102 | @Override 103 | public void advance(Duration duration) { 104 | advanceNanos(duration.toNanos()); 105 | } 106 | 107 | @Override 108 | public String toString() { 109 | return "FakeTicker{" 110 | + "ticksValue=" 111 | + ticksValue 112 | + ", fakeClocks.autoAdvanceDuration=" 113 | + fakeClocks.autoAdvanceDuration 114 | + '}'; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/MoreAsserts.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/MoreAsserts.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/PredictableRandom.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/PredictableRandom.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/base/testing/TestEnvironmentUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static org.junit.Assume.assumeFalse; 20 | 21 | import android.os.Build; 22 | import com.google.time.client.base.impl.Objects; 23 | 24 | /** 25 | * Methods to support tests that need to have different behaviors under different variant / 26 | * environments. 27 | * 28 | *

This is the Android variant of this class. 29 | */ 30 | public class TestEnvironmentUtils { 31 | private TestEnvironmentUtils() {} 32 | 33 | /** Returns {@code true} if the test is running the Java SE variant of code. */ 34 | public static boolean isThisJavaSe() { 35 | return false; 36 | } 37 | 38 | /** 39 | * Returns the Java version when the test is running the Java SE variant of code. Throws {@link 40 | * AssertionError} when on Android. 41 | */ 42 | @SuppressWarnings("DoNotCallSuggester") 43 | public static int getJavaVersion() { 44 | throw new AssertionError("This is the Android variant"); 45 | } 46 | 47 | /** Returns {@code true} if the test is running the Android variant of code. */ 48 | public static boolean isThisAndroid() { 49 | return true; 50 | } 51 | 52 | /** 53 | * Returns the Android API level when the test is running the Android variant of code. Throws 54 | * {@link AssertionError} when on Java SE. 55 | */ 56 | public static int getAndroidApiLevel() { 57 | return Build.VERSION.SDK_INT; 58 | } 59 | 60 | /** 61 | * Throws {@link org.junit.AssumptionViolatedException} if running the Android variant of code 62 | * under robolectric. 63 | */ 64 | public static void assumeNotRobolectric(String reason) { 65 | assumeFalse(reason, isThisRobolectric()); 66 | } 67 | 68 | /** Returns {@code true} if running the Android variant of code under robolectric. */ 69 | public static boolean isThisRobolectric() { 70 | // "robolectric" may also be acceptable. 71 | return Objects.equals(null, Build.FINGERPRINT); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library") 2 | 3 | android_library( 4 | name = "sntp", 5 | srcs = glob([ 6 | "*.java", 7 | "impl/*.java", 8 | ]), 9 | visibility = ["//visibility:public"], 10 | deps = [ 11 | "//java/com/google/time/client/base", 12 | "@maven//:com_google_errorprone_error_prone_annotations", 13 | ], 14 | ) 15 | 16 | javadoc_library( 17 | name = "sntp.javadocs", 18 | srcs = glob(["*.java"]), 19 | # TODO Fix Android API level 20 | android_api_level = 31, 21 | deps = [":sntp"], 22 | ) 23 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/BasicSntpClient.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/BasicSntpClient.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/InvalidNtpValueException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/InvalidNtpValueException.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/NtpProtocolException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/NtpProtocolException.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/NtpServerNotReachableException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/NtpServerNotReachableException.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/SntpClient.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpClient.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/SntpQueryDebugInfo.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpQueryDebugInfo.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/SntpQueryResult.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpQueryResult.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/SntpTimeSignal.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpTimeSignal.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/Duration64.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/Duration64.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/NtpDateTimeUtils.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/NtpDateTimeUtils.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/NtpHeader.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/NtpHeader.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/NtpMessage.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/NtpMessage.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SerializationUtils.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SerializationUtils.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SntpClientEngine.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpClientEngine.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SntpQueryOperation.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpQueryOperation.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SntpRequestFactory.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpRequestFactory.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SntpServiceConnector.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpServiceConnector.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SntpServiceConnectorImpl.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpServiceConnectorImpl.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/SntpTimeSignalImpl.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpTimeSignalImpl.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/impl/Timestamp64.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/Timestamp64.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/testing/BUILD.bazel: -------------------------------------------------------------------------------- 1 | android_library( 2 | name = "testing", 3 | testonly = 1, 4 | srcs = glob(["*.java"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//java/com/google/time/client/base", 8 | "//java/com/google/time/client/base/testing", 9 | "//java/com/google/time/client/sntp", 10 | "@maven//:junit_junit", 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/testing/FakeNetwork.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/FakeNetwork.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/testing/FakeSntpServerEngine.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/FakeSntpServerEngine.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/testing/SntpTestServer.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/SntpTestServer.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/testing/TestSntpServerEngine.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/TestSntpServerEngine.java -------------------------------------------------------------------------------- /android/java/com/google/time/client/sntp/testing/TestSntpServerWithNetwork.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/TestSntpServerWithNetwork.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/AndroidDateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertThrows; 21 | 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | @RunWith(JUnit4.class) 27 | public class AndroidDateTimeUtilsTest { 28 | 29 | @Test 30 | public void checkPositiveSubSecondNanos() { 31 | assertEquals(0, AndroidDateTimeUtils.checkPositiveSubSecondNanos(0)); 32 | assertEquals(1, AndroidDateTimeUtils.checkPositiveSubSecondNanos(1)); 33 | assertEquals(500_000_000, AndroidDateTimeUtils.checkPositiveSubSecondNanos(500_000_000)); 34 | assertEquals(999_999_999, AndroidDateTimeUtils.checkPositiveSubSecondNanos(999_999_999)); 35 | 36 | assertThrows( 37 | DateTimeException.class, 38 | () -> AndroidDateTimeUtils.checkPositiveSubSecondNanos(Integer.MIN_VALUE)); 39 | assertThrows( 40 | DateTimeException.class, () -> AndroidDateTimeUtils.checkPositiveSubSecondNanos(-1)); 41 | assertThrows( 42 | DateTimeException.class, 43 | () -> AndroidDateTimeUtils.checkPositiveSubSecondNanos(1_000_000_000)); 44 | assertThrows( 45 | DateTimeException.class, 46 | () -> AndroidDateTimeUtils.checkPositiveSubSecondNanos(Integer.MAX_VALUE)); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/AndroidTestManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//testing:test_defs.bzl", "gen_android_local_tests") 2 | 3 | gen_android_local_tests( 4 | name = "tests", 5 | srcs = glob([ 6 | "*.java", 7 | "impl/*.java", 8 | ]), 9 | deps = [ 10 | "//java/com/google/time/client/base", 11 | "//java/com/google/time/client/base/testing", 12 | "@maven//:com_google_truth_truth", 13 | "@maven//:org_mockito_mockito_core", 14 | "@maven//:org_robolectric_robolectric", 15 | "@robolectric//bazel:android-all", 16 | ], 17 | ) 18 | 19 | # TODO Remove duplication with other Android test libs. 20 | # Android: A library of tests for on-device tests. 21 | android_library( 22 | name = "libtests", 23 | srcs = glob([ 24 | "*.java", 25 | "impl/*.java", 26 | ]), 27 | deps = [ 28 | "//java/com/google/time/client/base", 29 | "//java/com/google/time/client/base/testing", 30 | "@maven//:androidx_test_core", 31 | "@maven//:androidx_test_runner", 32 | "@maven//:com_google_truth_truth", 33 | "@maven//:junit_junit", 34 | "@maven//:org_mockito_mockito_android", 35 | "@maven//:org_mockito_mockito_core", 36 | ], 37 | ) 38 | 39 | # Android: Instrumentation app for running on-device tests. 40 | android_binary( 41 | name = "tests.test_app", 42 | testonly = 1, 43 | custom_package = "com.google.time.client.base.test_app", 44 | instruments = ":tests.app", 45 | manifest = "AndroidTestManifest.xml", 46 | deps = [ 47 | ":libtests", 48 | ], 49 | ) 50 | 51 | # TODO Generalize android_binary if possible for use in base too. Tests can carry the code under test too? 52 | # Android: App containing the library for running on-device tests. 53 | android_binary( 54 | name = "tests.app", 55 | custom_package = "com.google.time.client.base.app", 56 | manifest = "AndroidManifest.xml", 57 | deps = ["//java/com/google/time/client/base"], 58 | ) 59 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/DurationTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/DurationTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/InstantTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/InstantTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/NetworkOperationResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/NetworkOperationResultTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/PlatformInstantSourceTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/PlatformInstantSourceTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/PlatformNetworkTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/PlatformNetworkTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/PlatformTickerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_MILLISECOND; 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertTrue; 22 | 23 | import android.os.SystemClock; 24 | import com.google.time.client.base.testing.TestEnvironmentUtils; 25 | import org.junit.Before; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.junit.runners.JUnit4; 29 | 30 | @RunWith(JUnit4.class) 31 | public class PlatformTickerTest { 32 | 33 | @Before 34 | public void setUp() { 35 | TestEnvironmentUtils.assumeNotRobolectric( 36 | "SystemClock.elapsedRealtimeNanos() doesn't appear to" 37 | + " work with bazel + robolectric 4.7.3"); 38 | } 39 | 40 | @Test 41 | public void ticksAndDurationBetween() throws Exception { 42 | Ticker ticker = PlatformTicker.instance(); 43 | 44 | long before1 = SystemClock.elapsedRealtimeNanos(); 45 | Ticks tick1 = ticker.ticks(); 46 | long after1 = SystemClock.elapsedRealtimeNanos(); 47 | 48 | Thread.sleep(250); 49 | 50 | long before2 = SystemClock.elapsedRealtimeNanos(); 51 | Ticks tick2 = ticker.ticks(); 52 | long after2 = SystemClock.elapsedRealtimeNanos(); 53 | 54 | Duration maxDuration = Duration.ofNanos(after2 - before1); 55 | Duration minDuration = Duration.ofNanos(before2 - after1); 56 | Duration durationBetweenTicks = tick1.durationUntil(tick2); 57 | 58 | assertTrue(durationBetweenTicks.compareTo(minDuration) >= 0); 59 | assertTrue(durationBetweenTicks.compareTo(maxDuration) <= 0); 60 | } 61 | 62 | @Test 63 | public void ticksPrecision() { 64 | Ticker ticker = PlatformTicker.instance(); 65 | 66 | // Try to prove that the ticker is precise below millis. 67 | Ticks ticks1 = ticker.ticks(); 68 | Ticks ticks2 = ticker.ticks(); 69 | Ticks ticks3 = ticker.ticks(); 70 | assertTrue( 71 | durationUntilHasNonZeroNanos(ticks1, ticks2) 72 | || durationUntilHasNonZeroNanos(ticks1, ticks3)); 73 | } 74 | 75 | private static boolean durationUntilHasNonZeroNanos(Ticks ticks1, Ticks ticks2) { 76 | return ticks1.durationUntil(ticks2).getNano() % NANOS_PER_MILLISECOND != 0; 77 | } 78 | 79 | @Test 80 | public void elapsedRealtimeNanosConversion() { 81 | AndroidTicker ticker = PlatformTicker.instance(); 82 | 83 | { 84 | long elapsedRealtimeNanos = 1234567890123L; 85 | Ticks nanoTicks = ticker.ticksForElapsedRealtimeNanos(elapsedRealtimeNanos); 86 | assertEquals(elapsedRealtimeNanos, ticker.valueForTicks(nanoTicks)); 87 | assertEquals(elapsedRealtimeNanos, ticker.elapsedRealtimeNanosForTicks(nanoTicks)); 88 | } 89 | 90 | { 91 | long elapsedRealtimeMillis = 1234567890L; 92 | Ticks millisTicks = ticker.ticksForElapsedRealtimeMillis(elapsedRealtimeMillis); 93 | assertEquals( 94 | elapsedRealtimeMillis * NANOS_PER_MILLISECOND, ticker.valueForTicks(millisTicks)); 95 | assertEquals(elapsedRealtimeMillis, ticker.elapsedRealtimeMillisForTicks(millisTicks)); 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/TickerTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/TickerTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/TicksTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/TicksTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/impl/ClusteredServiceOperationTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/impl/ClusteredServiceOperationTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/impl/ObjectsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/impl/ObjectsTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/impl/PlatformRandomTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/impl/PlatformRandomTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/AndroidTestManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//testing:test_defs.bzl", "gen_android_local_tests") 2 | 3 | gen_android_local_tests( 4 | name = "tests", 5 | srcs = glob(["*.java"]), 6 | deps = [ 7 | "//java/com/google/time/client/base", 8 | "//java/com/google/time/client/base/testing", 9 | "@maven//:com_google_truth_truth", 10 | "@maven//:org_robolectric_robolectric", 11 | "@robolectric//bazel:android-all", 12 | ], 13 | ) 14 | 15 | # TODO Remove duplication with other Android test libs. 16 | # Android: A library of tests for on-device tests. 17 | android_library( 18 | name = "libtests", 19 | srcs = glob(["*.java"]), 20 | deps = [ 21 | "//java/com/google/time/client/base", 22 | "//java/com/google/time/client/base/testing", 23 | "@maven//:androidx_test_core", 24 | "@maven//:androidx_test_runner", 25 | "@maven//:com_google_truth_truth", 26 | "@maven//:junit_junit", 27 | ], 28 | ) 29 | 30 | # Android: Instrumentation app for running on-device tests. 31 | android_binary( 32 | name = "tests.test_app", 33 | testonly = 1, 34 | custom_package = "com.google.time.client.base.testing.test_app", 35 | instruments = ":tests.app", 36 | manifest = "AndroidTestManifest.xml", 37 | deps = [ 38 | ":libtests", 39 | ], 40 | ) 41 | 42 | # TODO Generalize android_binary if possible for use in base too. Tests can carry the code under test too? 43 | # Android: App containing the library for running on-device tests. 44 | android_binary( 45 | name = "tests.app", 46 | custom_package = "com.google.time.client.base.testing.app", 47 | manifest = "AndroidManifest.xml", 48 | deps = ["//java/com/google/time/client/base/testing"], 49 | ) 50 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/BytesTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/BytesTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/DateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/DateTimeUtilsTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/FakeClocksTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/FakeClocksTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/FakeTickerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import com.google.time.client.base.AndroidTicker; 22 | import com.google.time.client.base.Ticks; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.junit.runners.JUnit4; 26 | 27 | @RunWith(JUnit4.class) 28 | public class FakeTickerTest { 29 | 30 | @Test 31 | public void implementsAndroidTicker() { 32 | FakeClocks fakeClocks = new FakeClocks(); 33 | AndroidTicker fakeTicker = fakeClocks.getFakeTicker(); 34 | { 35 | long elapsedRealtimeMillis = 1234; 36 | Ticks ticks = fakeTicker.ticksForElapsedRealtimeMillis(elapsedRealtimeMillis); 37 | assertEquals(elapsedRealtimeMillis, fakeTicker.elapsedRealtimeMillisForTicks(ticks)); 38 | } 39 | { 40 | long elapsedRealtimeNanos = 1234; 41 | Ticks ticks = fakeTicker.ticksForElapsedRealtimeNanos(elapsedRealtimeNanos); 42 | assertEquals(elapsedRealtimeNanos, fakeTicker.elapsedRealtimeNanosForTicks(ticks)); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/base/testing/PredictableRandomTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/PredictableRandomTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 20 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/AndroidTestManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 23 | 24 | 27 | 28 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//testing:test_defs.bzl", "gen_android_local_tests") 2 | 3 | # Android: A test_suite / generates robolectric tests. 4 | gen_android_local_tests( 5 | name = "tests", 6 | srcs = glob([ 7 | "*.java", 8 | "impl/*.java", 9 | ]), 10 | deps = [ 11 | "//java/com/google/time/client/base", 12 | "//java/com/google/time/client/base/testing", 13 | "//java/com/google/time/client/sntp", 14 | "//java/com/google/time/client/sntp/testing", 15 | "@maven//:com_google_truth_truth", 16 | "@maven//:org_mockito_mockito_core", 17 | "@maven//:org_robolectric_robolectric", 18 | "@robolectric//bazel:android-all", 19 | ], 20 | ) 21 | 22 | # TODO Remove duplication with other Android test libs. 23 | # Android: A library of tests for on-device tests. 24 | android_library( 25 | name = "libtests", 26 | srcs = glob([ 27 | "*.java", 28 | "impl/*.java", 29 | ]), 30 | deps = [ 31 | "//java/com/google/time/client/base", 32 | "//java/com/google/time/client/base/testing", 33 | "//java/com/google/time/client/sntp", 34 | "//java/com/google/time/client/sntp/testing", 35 | "@maven//:androidx_test_core", 36 | "@maven//:androidx_test_runner", 37 | "@maven//:com_google_truth_truth", 38 | "@maven//:junit_junit", 39 | "@maven//:org_mockito_mockito_android", 40 | "@maven//:org_mockito_mockito_core", 41 | ], 42 | ) 43 | 44 | # Android: Instrumentation app for running on-device tests. 45 | android_binary( 46 | name = "tests.test_app", 47 | testonly = 1, 48 | custom_package = "com.google.time.client.sntp.test_app", 49 | instruments = ":tests.app", 50 | manifest = "AndroidTestManifest.xml", 51 | deps = [ 52 | ":libtests", 53 | ], 54 | ) 55 | 56 | # TODO Generalize android_binary if possible for use in base too. Tests can carry the code under test too? 57 | # Android: App containing the library for running on-device tests. 58 | android_binary( 59 | name = "tests.app", 60 | custom_package = "com.google.time.client.sntp.app", 61 | manifest = "AndroidManifest.xml", 62 | deps = ["//java/com/google/time/client/sntp"], 63 | ) 64 | -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/BasicSntpClientTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/sntp/BasicSntpClientTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/SntpQueryDebugInfoTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/sntp/SntpQueryDebugInfoTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/SntpQueryResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/sntp/SntpQueryResultTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/Duration64Test.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/Duration64Test.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/NtpDateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/NtpDateTimeUtilsTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/NtpHeaderTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/NtpHeaderTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/NtpMessageTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/NtpMessageTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SerializationUtilsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SerializationUtilsTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpClientEngineNetworkingTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpClientEngineNetworkingTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpClientEngineUnitTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpClientEngineUnitTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpQueryOperationFailureResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationFailureResultTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpQueryOperationSuccessResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationSuccessResultTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpQueryOperationTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpRequestFactoryTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpRequestFactoryTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/SntpTimeSignalImplTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpTimeSignalImplTest.java -------------------------------------------------------------------------------- /android/javatests/com/google/time/client/sntp/impl/Timestamp64Test.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/Timestamp64Test.java -------------------------------------------------------------------------------- /android/run_device_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | SCRIPT_DIR=$(dirname $0) 18 | ANDROID_DIR=$(realpath ${SCRIPT_DIR}) 19 | ROOT_DIR=$(realpath ${ANDROID_DIR}/..) 20 | BAZEL_COMMAND="bazel --bazelrc=${ROOT_DIR}/java-time-client.bazelrc" 21 | 22 | cd ${ANDROID_DIR} 23 | 24 | RULES=( 25 | "//javatests/com/google/time/client/base:tests.app.apk" 26 | "//javatests/com/google/time/client/base:tests.test_app.apk" 27 | "//javatests/com/google/time/client/base/testing:tests.app.apk" 28 | "//javatests/com/google/time/client/base/testing:tests.test_app.apk" 29 | "//javatests/com/google/time/client/sntp:tests.app.apk" 30 | "//javatests/com/google/time/client/sntp:tests.test_app.apk" 31 | ) 32 | APKS=( 33 | "javatests/com/google/time/client/base/tests.app.apk" 34 | "javatests/com/google/time/client/base/tests.test_app.apk" 35 | "javatests/com/google/time/client/base/testing/tests.app.apk" 36 | "javatests/com/google/time/client/base/testing/tests.test_app.apk" 37 | "javatests/com/google/time/client/sntp/tests.app.apk" 38 | "javatests/com/google/time/client/sntp/tests.test_app.apk" 39 | ) 40 | PACKAGES=( 41 | "com.google.time.client.base" 42 | "com.google.time.client.base.test" 43 | "com.google.time.client.base.testing" 44 | "com.google.time.client.base.testing.test" 45 | "com.google.time.client.sntp" 46 | "com.google.time.client.sntp.test" 47 | ) 48 | TEST_PACKAGES=( 49 | "com.google.time.client.base.test" 50 | "com.google.time.client.base.testing.test" 51 | "com.google.time.client.sntp.test" 52 | ) 53 | 54 | # TODO There is a lot of scope to remove duplication above and below. 55 | set -e 56 | 57 | function echo_command() { echo $*; $*; } 58 | 59 | echo_command ${BAZEL_COMMAND} build ${RULES[@]} 60 | 61 | for APK in ${APKS[@]}; do 62 | echo_command adb install bazel-bin/${APK} 63 | done 64 | 65 | for TEST_PACKAGE in ${TEST_PACKAGES[@]}; do 66 | echo_command adb shell am instrument -w ${TEST_PACKAGE}/androidx.test.runner.AndroidJUnitRunner 67 | done 68 | 69 | for PACKAGE in ${PACKAGES[@]}; do 70 | echo_command adb uninstall ${PACKAGE} 71 | done 72 | 73 | -------------------------------------------------------------------------------- /before-upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # A "pre-submit" script that invokes various formatting / linting tools and runs 17 | # tests. 18 | 19 | SCRIPT_DIR=$(dirname $0) 20 | ROOT_DIR=$(realpath ${SCRIPT_DIR}) 21 | ORIG_DIR=$(pwd) 22 | BAZEL_COMMAND="bazel --bazelrc=${ROOT_DIR}/java-time-client.bazelrc" 23 | 24 | function echo_command() { echo $*; $*; } 25 | function print_separator() { echo "============================="; } 26 | 27 | if [[ ! -f ${ROOT_DIR}/java-time-client.config ]]; then 28 | echo Copy java-time-client.config_template to create java-time-client.config and edit it. 29 | exit 1 30 | fi 31 | 32 | source ${ROOT_DIR}/java-time-client.config 33 | 34 | print_separator 35 | echo Checking for unexpected dupes of common files... 36 | ${ROOT_DIR}/check-for-dupes-of-common.sh 37 | 38 | print_separator 39 | echo Formatting / linting... 40 | 41 | if [[ -z ${JAVA_FORMAT_JAR} ]]; then 42 | echo JAVA_FORMAT_JAR not set 43 | exit 1 44 | fi 45 | echo_command ${ROOT_DIR}/reformat-java.sh ${JAVA_FORMAT_JAR} 46 | 47 | echo_command ${ROOT_DIR}/regenerate-common-symlinks.sh > /dev/null 48 | echo_command ~/go/bin/buildifier -r --lint=warn ${ROOT_DIR} 49 | 50 | print_separator 51 | if [[ -z ${ANDROID_SDK} ]]; then 52 | echo ANDROID_SDK not set 53 | exit 1 54 | fi 55 | 56 | echo "Running Android tests with robolectric, ANDROID_HOME=${ANDROID_SDK}..." 57 | echo_command cd ${ROOT_DIR}/android 58 | ANDROID_HOME=${ANDROID_SDK} echo_command ${BAZEL_COMMAND} test ${BAZEL_BUILD_OPTIONS} //javatests/com/google/time/client/... 59 | 60 | print_separator 61 | cd ${ORIG_DIR} 62 | echo Running Java SE tests with bazel JDK... 63 | cd ${ROOT_DIR}/javase 64 | echo_command ${BAZEL_COMMAND} test ${BAZEL_BUILD_OPTIONS} //javatests/com/google/time/client/... 65 | 66 | print_separator 67 | if [[ -z ${JDK8} ]]; then 68 | echo JDK8 not set 69 | exit 1 70 | fi 71 | echo "Running Java SE tests with JDK 8 on path (${JDK8})..." 72 | PATH=${JDK8}/bin:${PATH} echo_command ${BAZEL_COMMAND} test ${BAZEL_BUILD_OPTIONS} --java_runtime_version=local_jdk //javatests/com/google/time/client/... 73 | 74 | print_separator 75 | cd ${ORIG_DIR} 76 | echo "Running Android tests on Android device (ANDROID_HOME=${ANDROID_SDK} for build and platform tooling)..." 77 | ANDROID_HOME=${ANDROID_SDK} PATH=${ANDROID_SDK}/platform-tools/:${PATH} echo_command ${ROOT_DIR}/android/run_device_tests.sh 78 | 79 | print_separator 80 | -------------------------------------------------------------------------------- /check-for-dupes-of-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # Checks for file names that exist in both common/ and either javase/ and 17 | # android/. The exit status code is 0 if no duplicate names exist. 18 | 19 | function report_if_exists() { 20 | F1=$1 21 | 22 | if [[ -f ${F1} && ! -L ${F1} ]]; then 23 | echo ${F1} exists and is also in common/. 24 | return 1 25 | fi 26 | return 0 27 | } 28 | 29 | PROJECT_ROOT=`dirname $0` 30 | 31 | COMMON_FILES_INFO=$(find ${PROJECT_ROOT}/common -type f -printf "%d|%f|%h|%H|%p|%P\n") 32 | DUPES_EXIST=0 33 | for FILE_INFO in ${COMMON_FILES_INFO}; do 34 | IFS="|" read -a FILE_INFO_ARR <<< ${FILE_INFO} 35 | RELATIVE_FILE=${FILE_INFO_ARR[5]} 36 | 37 | report_if_exists ${PROJECT_ROOT}/android/${RELATIVE_FILE} 38 | if (( $? != 0 )); then 39 | DUPES_EXIST=1 40 | fi 41 | 42 | report_if_exists ${PROJECT_ROOT}/javase/${RELATIVE_FILE} 43 | if (( $? != 0 )); then 44 | DUPES_EXIST=1 45 | fi 46 | done 47 | 48 | exit ${DUPES_EXIST} 49 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/DateTimeException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | /** 20 | * A stand-in for java.time.DateTimeException, which is not available on all platform versions 21 | * supported by java-time-client. 22 | */ 23 | public final class DateTimeException extends RuntimeException { 24 | 25 | public DateTimeException(Throwable e) { 26 | super(e); 27 | } 28 | 29 | public DateTimeException(String msg) { 30 | super(msg); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/InstantSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static com.google.time.client.base.impl.DateTimeConstants.MILLISECONDS_PER_SECOND; 20 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_SECOND; 21 | 22 | /** A source of instants. */ 23 | public abstract class InstantSource { 24 | 25 | /** Used to indicate Instants have millisecond precision. */ 26 | public static final int PRECISION_MILLIS = MILLISECONDS_PER_SECOND; 27 | 28 | /** Used to indicate Instants have nanosecond precision. */ 29 | public static final int PRECISION_NANOS = NANOS_PER_SECOND; 30 | 31 | /** Returns the current instant from the source. */ 32 | /*@NonNull*/ public abstract Instant instant(); 33 | 34 | /** Returns the underlying clock precision. */ 35 | public abstract int getPrecision(); 36 | } 37 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/Logger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | /** 20 | * A stand-in for java.util.logging.Logger, which is not available on all platform versions 21 | * supported by java-time-client. 22 | */ 23 | public interface Logger { 24 | 25 | boolean isLoggingFine(); 26 | 27 | void fine(String msg); 28 | 29 | void fine(String msg, Throwable e); 30 | 31 | void warning(String msg); 32 | 33 | void warning(String msg, Throwable e); 34 | } 35 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/Network.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.base; 17 | 18 | import java.io.IOException; 19 | import java.net.DatagramPacket; 20 | import java.net.InetAddress; 21 | import java.net.SocketAddress; 22 | import java.net.SocketException; 23 | import java.net.UnknownHostException; 24 | 25 | /** 26 | * An abstraction over basic networking behavior to aid with testing and to enable deployers of 27 | * network-based time sync clients to affect things like which network interface is used. 28 | */ 29 | public interface Network { 30 | 31 | InetAddress[] getAllByName(String hostString) throws UnknownHostException; 32 | 33 | UdpSocket createUdpSocket() throws IOException; 34 | 35 | /** A partial interface over {@link java.net.DatagramSocket} to make it easier to test with. */ 36 | interface UdpSocket extends AutoCloseable { 37 | 38 | SocketAddress getLocalSocketAddress(); 39 | 40 | void setSoTimeout(Duration timeout) throws SocketException; 41 | 42 | void send(DatagramPacket packet) throws IOException; 43 | 44 | void receive(DatagramPacket packet) throws IOException; 45 | 46 | void close(); 47 | 48 | boolean isClosed(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/PlatformInstantSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | /** 20 | * An {@link InstantSource} that provides millisecond-precision access to the default system clock, 21 | * i.e. via {@link System#currentTimeMillis()}. 22 | */ 23 | public final class PlatformInstantSource extends InstantSource { 24 | 25 | private static final PlatformInstantSource INSTANCE = new PlatformInstantSource(); 26 | 27 | public static InstantSource instance() { 28 | return INSTANCE; 29 | } 30 | 31 | private PlatformInstantSource() {} 32 | 33 | @Override 34 | public Instant instant() { 35 | return Instant.ofEpochMilli(System.currentTimeMillis()); 36 | } 37 | 38 | @Override 39 | public int getPrecision() { 40 | return PRECISION_MILLIS; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "PlatformInstantSource"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/PlatformNetwork.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import java.io.IOException; 20 | import java.net.DatagramPacket; 21 | import java.net.DatagramSocket; 22 | import java.net.InetAddress; 23 | import java.net.SocketAddress; 24 | import java.net.SocketException; 25 | import java.net.UnknownHostException; 26 | 27 | /** 28 | * Provides access to a generally suitable default {@link Network} instance. This implementation 29 | * uses stock Java APIs with no special behavior. 30 | */ 31 | public final class PlatformNetwork { 32 | 33 | private static final Network INSTANCE = new NetworkImpl(); 34 | 35 | public static Network instance() { 36 | return INSTANCE; 37 | } 38 | 39 | private PlatformNetwork() {} 40 | 41 | private static class NetworkImpl implements Network { 42 | @Override 43 | public InetAddress[] getAllByName(String hostString) throws UnknownHostException { 44 | return InetAddress.getAllByName(hostString); 45 | } 46 | 47 | @Override 48 | public UdpSocket createUdpSocket() throws SocketException { 49 | return new DefaultUdpSocket(); 50 | } 51 | } 52 | 53 | private static class DefaultUdpSocket implements Network.UdpSocket { 54 | 55 | private final DatagramSocket delegate; 56 | 57 | DefaultUdpSocket() throws SocketException { 58 | this(new DatagramSocket()); 59 | } 60 | 61 | DefaultUdpSocket(DatagramSocket delegate) { 62 | this.delegate = delegate; 63 | } 64 | 65 | @Override 66 | public SocketAddress getLocalSocketAddress() { 67 | return delegate.getLocalSocketAddress(); 68 | } 69 | 70 | @Override 71 | public void setSoTimeout(Duration timeout) throws SocketException { 72 | long timeoutMillis = timeout.toMillis(); 73 | if (timeoutMillis < 0 || timeoutMillis > Integer.MAX_VALUE) { 74 | throw new IllegalArgumentException("Invalid timeout: " + timeout); 75 | } 76 | delegate.setSoTimeout((int) timeoutMillis); 77 | } 78 | 79 | @Override 80 | public void send(DatagramPacket packet) throws IOException { 81 | delegate.send(packet); 82 | } 83 | 84 | @Override 85 | public void receive(DatagramPacket packet) throws IOException { 86 | delegate.receive(packet); 87 | } 88 | 89 | @Override 90 | public void close() { 91 | delegate.close(); 92 | } 93 | 94 | @Override 95 | public boolean isClosed() { 96 | return delegate.isClosed(); 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/ServerAddress.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import com.google.time.client.base.impl.Objects; 20 | 21 | /** A server's name and port. */ 22 | public final class ServerAddress { 23 | private final String name; 24 | private final int port; 25 | 26 | /** Creates an instance. */ 27 | public ServerAddress(String name, int port) { 28 | this.name = Objects.requireNonNull(name); 29 | this.port = port; 30 | } 31 | 32 | /** Returns the server's name. */ 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | /** Returns the server's port. */ 38 | public int getPort() { 39 | return port; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) { 45 | return true; 46 | } 47 | if (!(o instanceof ServerAddress)) { 48 | return false; 49 | } 50 | ServerAddress that = (ServerAddress) o; 51 | return port == that.port && name.equals(that.name); 52 | } 53 | 54 | @Override 55 | public int hashCode() { 56 | return Objects.hash(name, port); 57 | } 58 | 59 | @Override 60 | public String toString() { 61 | return "ServerAddress{" + "name='" + name + '\'' + ", port=" + port + '}'; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/Supplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | /** 20 | * A stand-in for java.util.function.Supplier, which is not available on all platform versions 21 | * supported by java-time-client. 22 | * 23 | * @param the type of the object supplied 24 | */ 25 | public interface Supplier { 26 | /** Returns the supplied object. */ 27 | T get(); 28 | } 29 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/annotations/NonFinalForTesting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.annotations; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | 22 | /** 23 | * A source-retention marker for classes that would be final but have been left non-final for 24 | * testing. 25 | */ 26 | @Retention(RetentionPolicy.SOURCE) 27 | public @interface NonFinalForTesting {} 28 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/annotations/VisibleForTesting.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.annotations; 18 | 19 | import java.lang.annotation.Retention; 20 | import java.lang.annotation.RetentionPolicy; 21 | 22 | /** 23 | * A source-retention marker for methods that are more public than they would naturally be for 24 | * testing. 25 | */ 26 | @Retention(RetentionPolicy.SOURCE) 27 | public @interface VisibleForTesting {} 28 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/impl/DateTimeConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | /** Date / time related constants that show up in code a lot and utility methods. */ 20 | public interface DateTimeConstants { 21 | int NANOS_PER_MILLISECOND = 1_000_000; 22 | int NANOS_PER_SECOND = 1_000_000_000; 23 | int MILLISECONDS_PER_SECOND = 1_000; 24 | } 25 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/impl/ExactMath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 The Guava Authors 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License 10 | * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 | * or implied. See the License for the specific language governing permissions and limitations under 12 | * the License. 13 | */ 14 | package com.google.time.client.base.impl; 15 | 16 | /** 17 | * Stand-ins for {@link Math} methods which are not available on all platform versions supported by 18 | * java-time-client. 19 | */ 20 | public final class ExactMath { 21 | 22 | private ExactMath() {} 23 | 24 | // A copy of Guava's LongMath.checkedAdd() method. 25 | /** 26 | * Returns the sum of {@code a} and {@code b}, provided it does not overflow. 27 | * 28 | * @throws ArithmeticException if {@code a + b} overflows in signed {@code long} arithmetic 29 | */ 30 | public static long addExact(long a, long b) { 31 | long result = a + b; 32 | checkNoOverflow((a ^ b) < 0 | (a ^ result) >= 0, "checkedAdd", a, b); 33 | return result; 34 | } 35 | 36 | // A copy of Guava's LongMath.checkedSubtract() method. 37 | /** 38 | * Returns the difference of {@code a} and {@code b}, provided it does not overflow. 39 | * 40 | * @throws ArithmeticException if {@code a - b} overflows in signed {@code long} arithmetic 41 | */ 42 | public static long subtractExact(long a, long b) { 43 | long result = a - b; 44 | checkNoOverflow((a ^ b) >= 0 | (a ^ result) >= 0, "checkedSubtract", a, b); 45 | return result; 46 | } 47 | 48 | // A copy of Guava's LongMath.checkedMultiply() method. 49 | /** 50 | * Returns the product of {@code a} and {@code b}, provided it does not overflow. 51 | * 52 | * @throws ArithmeticException if {@code a * b} overflows in signed {@code long} arithmetic 53 | */ 54 | public static long multiplyExact(long a, long b) { 55 | // Hacker's Delight, Section 2-12 56 | int leadingZeros = 57 | Long.numberOfLeadingZeros(a) 58 | + Long.numberOfLeadingZeros(~a) 59 | + Long.numberOfLeadingZeros(b) 60 | + Long.numberOfLeadingZeros(~b); 61 | /* 62 | * If leadingZeros > Long.SIZE + 1 it's definitely fine, if it's < Long.SIZE it's definitely 63 | * bad. We do the leadingZeros check to avoid the division below if at all possible. 64 | * 65 | * Otherwise, if b == Long.MIN_VALUE, then the only allowed values of a are 0 and 1. We take 66 | * care of all a < 0 with their own check, because in particular, the case a == -1 will 67 | * incorrectly pass the division check below. 68 | * 69 | * In all other cases, we check that either a is 0 or the result is consistent with division. 70 | */ 71 | if (leadingZeros > Long.SIZE + 1) { 72 | return a * b; 73 | } 74 | checkNoOverflow(leadingZeros >= Long.SIZE, "checkedMultiply", a, b); 75 | checkNoOverflow(a >= 0 | b != Long.MIN_VALUE, "checkedMultiply", a, b); 76 | long result = a * b; 77 | checkNoOverflow(a == 0 || result / a == b, "checkedMultiply", a, b); 78 | return result; 79 | } 80 | 81 | // A copy of Guava's MathPreconditions.checkNoOverflow(). 82 | private static void checkNoOverflow(boolean condition, String methodName, long a, long b) { 83 | if (!condition) { 84 | throw new ArithmeticException("overflow: " + methodName + "(" + a + ", " + b + ")"); 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/impl/NoOpLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import com.google.time.client.base.Logger; 20 | 21 | /** A Logger implementation that does nothing. */ 22 | public final class NoOpLogger implements Logger { 23 | 24 | private static final NoOpLogger INSTANCE = new NoOpLogger(); 25 | 26 | public static NoOpLogger instance() { 27 | return INSTANCE; 28 | } 29 | 30 | private NoOpLogger() {} 31 | 32 | @Override 33 | public boolean isLoggingFine() { 34 | return false; 35 | } 36 | 37 | @Override 38 | public void fine(String msg) {} 39 | 40 | @Override 41 | public void fine(String msg, Throwable e) {} 42 | 43 | @Override 44 | public void warning(String msg) {} 45 | 46 | @Override 47 | public void warning(String msg, Throwable e) {} 48 | } 49 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/impl/Objects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import java.util.Arrays; 20 | 21 | /** 22 | * A stand-in for java.util.Objects, which is not available on all platform versions supported by 23 | * java-time-client. 24 | */ 25 | public final class Objects { 26 | private Objects() {} 27 | 28 | /** 29 | * Returns the argument if it is non-null. Throws {@link java.lang.NullPointerException} if the 30 | * argument is {@code null}. 31 | */ 32 | public static T requireNonNull(T object) { 33 | return requireNonNull(object, null); 34 | } 35 | 36 | /** 37 | * Returns the argument if it is non-null. Throws {@link java.lang.NullPointerException} if the 38 | * argument is {@code null}. 39 | */ 40 | public static T requireNonNull(T object, String message) { 41 | if (object == null) { 42 | throw new NullPointerException(message); 43 | } 44 | return object; 45 | } 46 | 47 | /** Returns a hashCode value for the supplied arguments. */ 48 | public static int hash(Object... toHash) { 49 | return Arrays.hashCode(toHash); 50 | } 51 | 52 | /** 53 | * Returns {@code true} if both arguments are {@code null} or if {@link Object#equals} returns 54 | * {@code code}. 55 | */ 56 | public static boolean equals(Object one, Object two) { 57 | return one == two || (one != null && one.equals(two)); 58 | } 59 | 60 | /** 61 | * Returns the result of calling {@link Object#toString()} or "null" if {@code objectOrNull} is 62 | * {@code null}. 63 | */ 64 | public static String toString(Object objectOrNull) { 65 | return objectOrNull == null ? "null" : objectOrNull.toString(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/impl/SystemStreamLogger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import com.google.time.client.base.Logger; 20 | import java.io.PrintStream; 21 | 22 | /** A Logger implementation that uses System.out and System.err. */ 23 | public final class SystemStreamLogger implements Logger { 24 | 25 | private boolean loggingFine = false; 26 | 27 | @Override 28 | public boolean isLoggingFine() { 29 | return loggingFine; 30 | } 31 | 32 | public void setLoggingFine(boolean fineLogging) { 33 | loggingFine = fineLogging; 34 | } 35 | 36 | @Override 37 | public void fine(String msg) { 38 | fine(msg, null); 39 | } 40 | 41 | @Override 42 | public void fine(String msg, Throwable e) { 43 | if (!loggingFine) { 44 | return; 45 | } 46 | log(System.out, "F", msg, e); 47 | } 48 | 49 | @Override 50 | public void warning(String msg) { 51 | warning(msg, null); 52 | } 53 | 54 | @Override 55 | public void warning(String msg, Throwable e) { 56 | log(System.err, "W", msg, e); 57 | } 58 | 59 | private static void log(PrintStream stream, String level, String msg, Throwable e) { 60 | stream.print(level); 61 | stream.print(" "); 62 | stream.println(msg); 63 | 64 | if (e != null) { 65 | stream.print(level); 66 | stream.print(" "); 67 | e.printStackTrace(stream); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/Advanceable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import com.google.time.client.base.Duration; 20 | 21 | /** A common interface for test clocks that can be advanced manually during tests. */ 22 | public interface Advanceable { 23 | /** Advance by the specified amount of time. */ 24 | void advance(Duration duration); 25 | } 26 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/Bytes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | /** Utility methods associated with primitive bytes and {@link java.lang.Byte}. */ 20 | public final class Bytes { 21 | 22 | private Bytes() {} 23 | 24 | /** 25 | * Coerces ints into bytes. Will accept anything in the range -128 to 255. i.e. it accepts values 26 | * that can be interpreted as signed or unsigned. 27 | */ 28 | public static byte[] bytes(int... ints) { 29 | byte[] bytes = new byte[ints.length]; 30 | for (int i = 0; i < ints.length; i++) { 31 | int byteAsInt = ints[i]; 32 | if (byteAsInt < -128 || byteAsInt > 255) { 33 | throw new ArithmeticException("Value outside signed and unsigned byte range:" + byteAsInt); 34 | } 35 | bytes[i] = (byte) byteAsInt; 36 | } 37 | return bytes; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static com.google.time.client.base.impl.DateTimeConstants.MILLISECONDS_PER_SECOND; 20 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_SECOND; 21 | 22 | import com.google.time.client.base.Instant; 23 | import java.util.GregorianCalendar; 24 | import java.util.TimeZone; 25 | 26 | /** Testing support for date / time. */ 27 | public final class DateTimeUtils { 28 | 29 | private DateTimeUtils() {} 30 | 31 | /** 32 | * Constructs an Instant equivalent to the specified UTC time. Avoids the use of 33 | * java.time.LocalDateTime, which isn't available on all platforms supported by java-time-client. 34 | */ 35 | public static Instant utc( 36 | int year, int monthOfYear, int day, int hour, int minute, int second, int nanosOfSecond) { 37 | 38 | // Do basic validation to catch obviously bad test data. Calendar with lenient mode off should 39 | // catch the rest. 40 | checkRange(year, 1900, 2100); // Arbitrary range 41 | checkRange(nanosOfSecond, 0, NANOS_PER_SECOND - 1); 42 | 43 | GregorianCalendar calendar = new GregorianCalendar(TimeZone.getTimeZone("GMT")); 44 | calendar.setLenient(false); 45 | calendar.clear(); 46 | 47 | int calendarMonth = monthOfYear - 1; 48 | calendar.set(year, calendarMonth, day, hour, minute, second); 49 | long epochMillis = calendar.getTimeInMillis(); 50 | long instantSeconds = epochMillis / MILLISECONDS_PER_SECOND; 51 | return Instant.ofEpochSecond(instantSeconds, nanosOfSecond); 52 | } 53 | 54 | private static void checkRange(int value, int minInc, int maxInc) { 55 | if (value < minInc || value > maxInc) { 56 | throw new IllegalArgumentException( 57 | value + " is outside of the range [" + minInc + ", " + maxInc + "]"); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/FakeClocks.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.base.testing; 17 | 18 | import com.google.time.client.base.Duration; 19 | import com.google.time.client.base.InstantSource; 20 | import com.google.time.client.base.Ticker; 21 | 22 | /** 23 | * A source of fake {@link Ticker} and {@link InstantSource} objects that can be made to advance 24 | * with each other automatically each time they are accessed via methods on this class. The 25 | * individual clocks can be advanced independently via methods on each. 26 | */ 27 | public final class FakeClocks implements Advanceable { 28 | 29 | private final FakeInstantSource fakeInstantSource = new FakeInstantSource(this); 30 | private final FakeTicker fakeTicker = new FakeTicker(this); 31 | 32 | Duration autoAdvanceDuration = Duration.ZERO; 33 | 34 | /** Clock is automatically advanced before the time is read. */ 35 | public void setAutoAdvanceNanos(long autoAdvanceNanos) { 36 | this.autoAdvanceDuration = Duration.ofNanos(autoAdvanceNanos); 37 | } 38 | 39 | /** Clock is automatically advanced before the time is read. */ 40 | public void setAutoAdvanceDuration(Duration autoAdvanceDuration) { 41 | this.autoAdvanceDuration = autoAdvanceDuration; 42 | } 43 | 44 | /** Returns the {@link FakeInstantSource}. */ 45 | public FakeInstantSource getFakeInstantSource() { 46 | return fakeInstantSource; 47 | } 48 | 49 | /** Returns the {@link FakeTicker}. */ 50 | public FakeTicker getFakeTicker() { 51 | return fakeTicker; 52 | } 53 | 54 | @Override 55 | public void advance(Duration duration) { 56 | fakeInstantSource.advance(duration); 57 | fakeTicker.advance(duration); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/FakeInstantSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.base.testing; 17 | 18 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_MILLISECOND; 19 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_SECOND; 20 | 21 | import com.google.time.client.base.Duration; 22 | import com.google.time.client.base.Instant; 23 | import com.google.time.client.base.InstantSource; 24 | import com.google.time.client.base.impl.Objects; 25 | 26 | /** 27 | * A fake {@link InstantSource} that can be used for tests. See {@link FakeClocks} for how to obtain 28 | * an instance. 29 | * 30 | *

By default, this instant source simulates one that returns instants with millisecond 31 | * precision, but this can be changed. 32 | */ 33 | public final class FakeInstantSource extends InstantSource implements Advanceable { 34 | 35 | private Instant instantSourceNow = Instant.ofEpochMilli(0); 36 | private int precision = InstantSource.PRECISION_MILLIS; 37 | 38 | private final FakeClocks fakeClocks; 39 | 40 | FakeInstantSource(FakeClocks fakeClocks) { 41 | this.fakeClocks = Objects.requireNonNull(fakeClocks); 42 | } 43 | 44 | @Override 45 | public int getPrecision() { 46 | return precision; 47 | } 48 | 49 | @Override 50 | public Instant instant() { 51 | instantSourceNow = instantSourceNow.plus(fakeClocks.autoAdvanceDuration); 52 | if (precision == PRECISION_MILLIS) { 53 | return Instant.ofEpochMilli(instantSourceNow.toEpochMilli()); 54 | } else if (precision == PRECISION_NANOS) { 55 | return instantSourceNow; 56 | } 57 | throw new IllegalStateException("Unknown resolution=" + precision); 58 | } 59 | 60 | /** Advance this instant source by the specified number of milliseconds. */ 61 | public void advanceMillis(long millis) { 62 | advance(Duration.ofNanos(millis * NANOS_PER_MILLISECOND)); 63 | } 64 | 65 | /** Advance this instant source by the specified duration. */ 66 | @Override 67 | public void advance(Duration duration) { 68 | instantSourceNow = instantSourceNow.plus(duration); 69 | } 70 | 71 | public void setEpochMillis(long epochMillis) { 72 | instantSourceNow = Instant.ofEpochMilli(epochMillis); 73 | } 74 | 75 | public void setInstant(Instant instant) { 76 | instantSourceNow = instant; 77 | } 78 | 79 | /** Returns the current instant. Does not auto advance. */ 80 | public Instant getCurrentInstant() { 81 | return instantSourceNow; 82 | } 83 | 84 | public void setPrecision(int precision) { 85 | this.precision = precision; 86 | } 87 | 88 | public void setEpochNanos(long epochNanos) { 89 | long seconds = epochNanos / NANOS_PER_SECOND; 90 | long nanos = epochNanos % NANOS_PER_SECOND; 91 | if (epochNanos < 0) { 92 | seconds--; 93 | nanos += NANOS_PER_SECOND; 94 | } 95 | instantSourceNow = Instant.ofEpochSecond(seconds, nanos); 96 | } 97 | 98 | @Override 99 | public String toString() { 100 | return "FakeInstantSource{" 101 | + "instantSourceNow=" 102 | + instantSourceNow 103 | + ", resolution=" 104 | + precision 105 | + ", fakeClocks.autoAdvanceDuration=" 106 | + fakeClocks.autoAdvanceDuration 107 | + '}'; 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/MoreAsserts.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | /** Useful assertions. */ 22 | public final class MoreAsserts { 23 | 24 | private MoreAsserts() {} 25 | 26 | public static > void assertComparisonMethods(T one, T two) { 27 | assertSelfComparison(one); 28 | assertSelfComparison(two); 29 | 30 | assertEquals(0, one.compareTo(two)); 31 | assertEquals(0, two.compareTo(one)); 32 | assertEquals(one, two); 33 | assertEquals(two.hashCode(), one.hashCode()); 34 | } 35 | 36 | @SuppressWarnings("SelfComparison") 37 | private static > void assertSelfComparison(T obj) { 38 | assertEquals(obj, obj); 39 | assertEquals(0, obj.compareTo(obj)); 40 | assertEquals(obj.hashCode(), obj.hashCode()); 41 | } 42 | 43 | public static void assertEqualityMethods(T one, T two) { 44 | assertSelfEquality(one); 45 | assertSelfEquality(two); 46 | 47 | assertEquals(one, two); 48 | assertEquals(two.hashCode(), one.hashCode()); 49 | } 50 | 51 | @SuppressWarnings("SelfComparison") 52 | private static void assertSelfEquality(T obj) { 53 | assertEquals(obj, obj); 54 | assertEquals(obj.hashCode(), obj.hashCode()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/base/testing/PredictableRandom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import java.util.Random; 20 | 21 | /** A fully deterministic {@link Random} for use in tests. */ 22 | public final class PredictableRandom extends Random { 23 | 24 | private int[] intSequence = new int[] {1}; 25 | 26 | private int intPos = 0; 27 | 28 | public PredictableRandom() {} 29 | 30 | public PredictableRandom(int... intSequence) { 31 | setIntSequence(intSequence); 32 | } 33 | 34 | public void setIntSequence(int... intSequence) { 35 | this.intSequence = intSequence; 36 | } 37 | 38 | @Override 39 | public int nextInt() { 40 | int value = intSequence[intPos++]; 41 | intPos %= intSequence.length; 42 | return value; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/InvalidNtpValueException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp; 18 | 19 | /** Thrown if a value contained in an NTP message is invalid. */ 20 | public final class InvalidNtpValueException extends Exception { 21 | 22 | public InvalidNtpValueException(String message) { 23 | super(message); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/NtpProtocolException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp; 18 | 19 | /** Thrown when an invalid NTP server response is detected. */ 20 | public final class NtpProtocolException extends Exception { 21 | 22 | public NtpProtocolException(String message) { 23 | super(message); 24 | } 25 | 26 | public NtpProtocolException(String message, Throwable e) { 27 | super(message, e); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/NtpServerNotReachableException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp; 18 | 19 | /** Thrown if communication with the NTP server failed. */ 20 | public final class NtpServerNotReachableException extends Exception { 21 | 22 | public NtpServerNotReachableException(String message) { 23 | super(message); 24 | } 25 | 26 | public NtpServerNotReachableException(String message, Throwable e) { 27 | super(message, e); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/SntpClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp; 18 | 19 | import com.google.time.client.base.Duration; 20 | import java.net.UnknownHostException; 21 | 22 | /** 23 | * A high-level API for obtaining an instant with metadata using SNTP. Implementations may provide 24 | * different behaviors around network fail-over and timeouts, security guarantees, consensus 25 | * generation, accuracy estimates or guarantees, and so on. 26 | */ 27 | public interface SntpClient { 28 | 29 | /** 30 | * Queries the current time from an NTP server using SNTP. 31 | * 32 | * @param timeAllowed the time allowed or {@code null} for indefinite. The time allowed is 33 | * considered a guide and may be exceeded 34 | * @return the result containing the current time from the server with metadata, or information 35 | * about the failure, never {@code null} 36 | */ 37 | SntpQueryResult executeQuery(Duration timeAllowed) throws UnknownHostException; 38 | } 39 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/SntpQueryDebugInfo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.sntp; 17 | 18 | import com.google.time.client.base.NetworkOperationResult; 19 | import com.google.time.client.base.impl.Objects; 20 | import java.net.InetAddress; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | * Information about a SNTP query that could be useful for debugging, metrics and alerting about 26 | * server or networking problems. 27 | */ 28 | public final class SntpQueryDebugInfo { 29 | 30 | private final List sntpQueryAddresses = new ArrayList<>(); 31 | private final List sntpQueryOperationResults = new ArrayList<>(); 32 | 33 | /** 34 | * @param sntpQueryAddresses the list of IP addresses that were resolved for the SNTP query 35 | */ 36 | public SntpQueryDebugInfo(List sntpQueryAddresses) { 37 | this.sntpQueryAddresses.addAll(sntpQueryAddresses); 38 | } 39 | 40 | /** 41 | * Adds a {@link NetworkOperationResult} for a single SNTP query operation. The results must be 42 | * added in the same order as {@link #getSntpQueryAddresses()}. 43 | */ 44 | public void addSntpQueryOperationResults(NetworkOperationResult sntpQueryOperationResult) { 45 | int nextResultIndex = sntpQueryOperationResults.size(); 46 | if (nextResultIndex >= sntpQueryAddresses.size()) { 47 | throw new IllegalArgumentException("No more operations expected"); 48 | } 49 | 50 | InetAddress resultAddress = sntpQueryOperationResult.getSocketAddress().getAddress(); 51 | if (!resultAddress.equals(sntpQueryAddresses.get(nextResultIndex))) { 52 | throw new IllegalArgumentException( 53 | "InetAddress at position " 54 | + nextResultIndex 55 | + " does not match " 56 | + sntpQueryOperationResult); 57 | } 58 | sntpQueryOperationResults.add(sntpQueryOperationResult); 59 | } 60 | 61 | /** Returns the list of IP addresses that were resolved for the SNTP query. */ 62 | public List getSntpQueryAddresses() { 63 | return new ArrayList<>(sntpQueryAddresses); 64 | } 65 | 66 | /** 67 | * Returns the results of network operations conducted for the SNTP query. This will contain one 68 | * or more results related to the addresses from {@link #getSntpQueryAddresses()}. 69 | */ 70 | public List getSntpQueryOperationResults() { 71 | return new ArrayList<>(sntpQueryOperationResults); 72 | } 73 | 74 | @Override 75 | public boolean equals(Object o) { 76 | if (this == o) { 77 | return true; 78 | } 79 | if (o == null || getClass() != o.getClass()) { 80 | return false; 81 | } 82 | SntpQueryDebugInfo that = (SntpQueryDebugInfo) o; 83 | return sntpQueryAddresses.equals(that.sntpQueryAddresses) 84 | && sntpQueryOperationResults.equals(that.sntpQueryOperationResults); 85 | } 86 | 87 | @Override 88 | public int hashCode() { 89 | return Objects.hash(sntpQueryAddresses, sntpQueryOperationResults); 90 | } 91 | 92 | @Override 93 | public String toString() { 94 | return "SntpQueryDebugInfo{" 95 | + "sntpQueryAddresses=" 96 | + sntpQueryAddresses 97 | + ", sntpQueryOperationResults=" 98 | + sntpQueryOperationResults 99 | + '}'; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/impl/NtpDateTimeUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.impl; 18 | 19 | import com.google.time.client.base.impl.DateTimeConstants; 20 | import java.util.Random; 21 | 22 | /** Utility functions associated with NTP data types. */ 23 | final class NtpDateTimeUtils { 24 | 25 | /** 26 | * The maximum value for the number of seconds in NTP data types when represented as a 32-bit 27 | * unsigned value. 28 | */ 29 | static final long MAX_32BIT_SECONDS_VALUE = 0xFFFF_FFFFL; 30 | 31 | private NtpDateTimeUtils() {} 32 | 33 | static int fractionBitsToNanos(int fractionBits) { 34 | long fractionBitsLong = fractionBits & 0xFFFF_FFFFL; 35 | return (int) ((fractionBitsLong * DateTimeConstants.NANOS_PER_SECOND) >>> 32); 36 | } 37 | 38 | static int nanosToFractionBits(long nanos) { 39 | if (nanos > DateTimeConstants.NANOS_PER_SECOND) { 40 | throw new IllegalArgumentException(); 41 | } 42 | return (int) ((nanos << 32) / DateTimeConstants.NANOS_PER_SECOND); 43 | } 44 | 45 | static int randomizeLowestBits(Random random, int value, int bitsToRandomize) { 46 | if (bitsToRandomize < 1 || bitsToRandomize >= Integer.SIZE) { 47 | // There's no point in randomizing all bits or none of the bits. 48 | throw new IllegalArgumentException(Integer.toString(bitsToRandomize)); 49 | } 50 | 51 | int upperBitMask = 0xFFFF_FFFF << bitsToRandomize; 52 | int lowerBitMask = ~upperBitMask; 53 | 54 | int randomValue = random.nextInt(); 55 | return (value & upperBitMask) | (randomValue & lowerBitMask); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/impl/SntpServiceConnector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.impl; 18 | 19 | import com.google.time.client.base.Duration; 20 | import com.google.time.client.base.impl.ClusteredServiceOperation.ClusteredServiceResult; 21 | import com.google.time.client.sntp.impl.SntpQueryOperation.FailureResult; 22 | import com.google.time.client.sntp.impl.SntpQueryOperation.SuccessResult; 23 | import java.net.UnknownHostException; 24 | 25 | /** 26 | * The interface for classes that handle routing requests to a clustered SNTP service. 27 | * 28 | *

This interface exists as an aid to testing: It hides the details of server addressing / 29 | * configuration so the caller doesn't have to provide a server address. 30 | */ 31 | public interface SntpServiceConnector { 32 | 33 | /** Sends an SNTP request to a clustered NTP server. */ 34 | ClusteredServiceResult executeQuery(Duration timeAllowed) 35 | throws UnknownHostException; 36 | } 37 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/impl/SntpServiceConnectorImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.impl; 18 | 19 | import com.google.time.client.base.Duration; 20 | import com.google.time.client.base.impl.ClusteredServiceOperation; 21 | import com.google.time.client.base.impl.ClusteredServiceOperation.ClusteredServiceResult; 22 | import com.google.time.client.base.impl.Objects; 23 | import com.google.time.client.sntp.BasicSntpClient.ClientConfig; 24 | import com.google.time.client.sntp.impl.SntpQueryOperation.FailureResult; 25 | import com.google.time.client.sntp.impl.SntpQueryOperation.SuccessResult; 26 | import java.net.UnknownHostException; 27 | 28 | /** 29 | * The real {@link SntpServiceConnector} implementation. 30 | * 31 | *

An adapter from {@link SntpServiceConnector} to {@link ClusteredServiceOperation}. 32 | */ 33 | public final class SntpServiceConnectorImpl implements SntpServiceConnector { 34 | 35 | private final ClientConfig clientConfig; 36 | private final ClusteredServiceOperation 37 | clusteredServiceOperation; 38 | 39 | public SntpServiceConnectorImpl( 40 | ClientConfig clientConfig, 41 | ClusteredServiceOperation clusteredServiceOperation) { 42 | this.clientConfig = Objects.requireNonNull(clientConfig); 43 | this.clusteredServiceOperation = Objects.requireNonNull(clusteredServiceOperation); 44 | } 45 | 46 | public ClientConfig getClientConfig() { 47 | return clientConfig; 48 | } 49 | 50 | @Override 51 | public ClusteredServiceResult executeQuery(Duration timeAllowed) 52 | throws UnknownHostException { 53 | Void parameter = null; 54 | return clusteredServiceOperation.execute( 55 | clientConfig.serverAddress().getName(), parameter, timeAllowed); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/testing/SntpTestServer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.testing; 18 | 19 | import static org.junit.Assert.fail; 20 | 21 | import com.google.time.client.base.impl.Objects; 22 | import com.google.time.client.sntp.impl.NtpMessage; 23 | import java.io.IOException; 24 | import java.net.DatagramPacket; 25 | import java.net.DatagramSocket; 26 | import java.net.InetAddress; 27 | import java.net.InetSocketAddress; 28 | import java.net.SocketException; 29 | 30 | /** Exposes a {@link TestSntpServerEngine} on a real network socket. */ 31 | final class SntpTestServer { 32 | 33 | private final Object lock = new Object(); 34 | private final DatagramSocket socket; 35 | private final Thread mListeningThread; 36 | private volatile boolean running; 37 | 38 | public SntpTestServer(TestSntpServerEngine engine) { 39 | Objects.requireNonNull(engine); 40 | socket = makeServerSocket(); 41 | running = true; 42 | 43 | mListeningThread = 44 | new Thread() { 45 | public void run() { 46 | try { 47 | while (running) { 48 | byte[] buffer = new byte[512]; 49 | DatagramPacket requestPacket = new DatagramPacket(buffer, buffer.length); 50 | try { 51 | socket.receive(requestPacket); 52 | } catch (IOException e) { 53 | fail("datagram receive error: " + e); 54 | break; 55 | } 56 | 57 | NtpMessage request = NtpMessage.fromDatagramPacket(requestPacket); 58 | synchronized (lock) { 59 | NtpMessage response = engine.processRequest(request); 60 | byte[] responseBytes = response.toBytes(); 61 | DatagramPacket responsePacket = 62 | new DatagramPacket( 63 | responseBytes, 64 | 0, 65 | responseBytes.length, 66 | requestPacket.getAddress(), 67 | requestPacket.getPort()); 68 | try { 69 | socket.send(responsePacket); 70 | } catch (IOException e) { 71 | fail("datagram send error: " + e); 72 | break; 73 | } 74 | } 75 | } 76 | } finally { 77 | socket.close(); 78 | } 79 | } 80 | }; 81 | mListeningThread.start(); 82 | } 83 | 84 | public void stop() { 85 | running = false; 86 | mListeningThread.interrupt(); 87 | } 88 | 89 | private DatagramSocket makeServerSocket() { 90 | DatagramSocket socket; 91 | try { 92 | socket = new DatagramSocket(0, InetAddress.getLoopbackAddress()); 93 | } catch (SocketException e) { 94 | fail("Failed to create test server socket: " + e); 95 | return null; 96 | } 97 | return socket; 98 | } 99 | 100 | public InetSocketAddress getInetSocketAddress() { 101 | return (InetSocketAddress) socket.getLocalSocketAddress(); 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /common/java/com/google/time/client/sntp/testing/TestSntpServerEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.testing; 18 | 19 | import com.google.time.client.sntp.impl.NtpMessage; 20 | 21 | /** Test logic for handling an SNTP request. */ 22 | public interface TestSntpServerEngine { 23 | NtpMessage processRequest(NtpMessage request); 24 | 25 | int numRequestsReceived(); 26 | } 27 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/PlatformInstantSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_MILLISECOND; 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertTrue; 22 | 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.junit.runners.JUnit4; 26 | 27 | @RunWith(JUnit4.class) 28 | public class PlatformInstantSourceTest { 29 | 30 | @Test 31 | public void precision() { 32 | InstantSource instantSource = PlatformInstantSource.instance(); 33 | assertEquals(InstantSource.PRECISION_MILLIS, instantSource.getPrecision()); 34 | assertEquals(0, instantSource.instant().getNano() % NANOS_PER_MILLISECOND); 35 | assertEquals(0, instantSource.instant().getNano() % NANOS_PER_MILLISECOND); 36 | assertEquals(0, instantSource.instant().getNano() % NANOS_PER_MILLISECOND); 37 | } 38 | 39 | @Test 40 | public void instant() { 41 | long before = System.currentTimeMillis(); 42 | Instant instant = PlatformInstantSource.instance().instant(); 43 | long after = System.currentTimeMillis(); 44 | 45 | long instantEpochMillis = instant.toEpochMilli(); 46 | assertTrue(instantEpochMillis >= before && instantEpochMillis <= after); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/PlatformNetworkTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static com.google.time.client.base.testing.Bytes.bytes; 20 | import static org.junit.Assert.assertArrayEquals; 21 | import static org.junit.Assert.assertEquals; 22 | 23 | import com.google.time.client.base.Network.UdpSocket; 24 | import java.net.DatagramPacket; 25 | import java.net.DatagramSocket; 26 | import java.net.InetAddress; 27 | import java.net.SocketAddress; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.JUnit4; 31 | 32 | @RunWith(JUnit4.class) 33 | public class PlatformNetworkTest { 34 | 35 | @Test 36 | public void getAllByName() throws Exception { 37 | Network network = PlatformNetwork.instance(); 38 | String hostString = "localhost"; 39 | assertArrayEquals(InetAddress.getAllByName(hostString), network.getAllByName(hostString)); 40 | } 41 | 42 | @Test 43 | public void udpSocketBehavior() throws Exception { 44 | Network network = PlatformNetwork.instance(); 45 | UdpSocket wrappedSocket = network.createUdpSocket(); 46 | wrappedSocket.setSoTimeout(Duration.ofSeconds(5, 0)); 47 | 48 | DatagramSocket javaSocket = new DatagramSocket(); 49 | javaSocket.setSoTimeout(5000); 50 | { 51 | byte[] sendBuf = bytes(1, 2, 3); 52 | SocketAddress javaSocketAddress = javaSocket.getLocalSocketAddress(); 53 | DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, javaSocketAddress); 54 | wrappedSocket.send(sendPacket); 55 | 56 | byte[] receiveBuf = new byte[100]; 57 | DatagramPacket receivePacket = new DatagramPacket(receiveBuf, receiveBuf.length); 58 | javaSocket.receive(receivePacket); 59 | assertEquals(3, receivePacket.getLength()); 60 | byte[] receivedBytes = new byte[3]; 61 | System.arraycopy(receiveBuf, 0, receivedBytes, 0, 3); 62 | assertArrayEquals(sendBuf, receivedBytes); 63 | } 64 | 65 | { 66 | byte[] sendBuf = bytes(3, 2, 1); 67 | SocketAddress wrappedSocketAddress = wrappedSocket.getLocalSocketAddress(); 68 | DatagramPacket sendPacket = new DatagramPacket(sendBuf, sendBuf.length, wrappedSocketAddress); 69 | javaSocket.send(sendPacket); 70 | 71 | byte[] receiveBuf = new byte[100]; 72 | DatagramPacket receivePacket = new DatagramPacket(receiveBuf, receiveBuf.length); 73 | wrappedSocket.receive(receivePacket); 74 | assertEquals(3, receivePacket.getLength()); 75 | byte[] receivedBytes = new byte[3]; 76 | System.arraycopy(receiveBuf, 0, receivedBytes, 0, 3); 77 | assertArrayEquals(sendBuf, receivedBytes); 78 | } 79 | 80 | wrappedSocket.close(); 81 | javaSocket.close(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/TickerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertThrows; 21 | import static org.junit.Assert.fail; 22 | 23 | import com.google.time.client.base.impl.ExactMath; 24 | import org.junit.Test; 25 | import org.junit.runner.RunWith; 26 | import org.junit.runners.JUnit4; 27 | 28 | @RunWith(JUnit4.class) 29 | public class TickerTest { 30 | 31 | @Test 32 | public void incrementsBetween() { 33 | TestTicker ticker = new TestTicker(); 34 | doIncrementsBetweenTest(ticker, 0, 1); 35 | doIncrementsBetweenTest(ticker, 0, -1); 36 | doIncrementsBetweenTest(ticker, 1, 1); 37 | doIncrementsBetweenTest(ticker, 1, -1); 38 | doIncrementsBetweenTest(ticker, Long.MIN_VALUE, 1); 39 | doIncrementsBetweenTest(ticker, Long.MIN_VALUE, Long.MAX_VALUE); 40 | doIncrementsBetweenTest(ticker, Long.MAX_VALUE, -1); 41 | doIncrementsBetweenTest(ticker, Long.MAX_VALUE, -Long.MAX_VALUE); 42 | 43 | // (0 - Long.MIN_VALUE) > Long.MAX_VALUE so must overflow. 44 | assertThrows( 45 | ArithmeticException.class, 46 | () -> 47 | ticker.incrementsBetween( 48 | ticker.forTickerValue(Long.MIN_VALUE), ticker.forTickerValue(0))); 49 | } 50 | 51 | private static void doIncrementsBetweenTest(TestTicker ticker, long tickerValue, long increment) { 52 | Ticks t1 = ticker.forTickerValue(tickerValue); 53 | Ticks t2 = ticker.forTickerValue(ExactMath.addExact(tickerValue, increment)); 54 | if (willSubtractionOverflow(ticker.valueForTicks(t2), ticker.valueForTicks(t1))) { 55 | fail("Bad test"); 56 | } else { 57 | assertEquals(increment, ticker.incrementsBetween(t1, t2)); 58 | } 59 | 60 | if (willSubtractionOverflow(ticker.valueForTicks(t1), ticker.valueForTicks(t2))) { 61 | fail("Bad test"); 62 | } else { 63 | assertEquals(-increment, ticker.incrementsBetween(t2, t1)); 64 | } 65 | } 66 | 67 | private static boolean willSubtractionOverflow(long one, long two) { 68 | try { 69 | ExactMath.subtractExact(one, two); 70 | return false; 71 | } catch (ArithmeticException e) { 72 | return false; 73 | } 74 | } 75 | 76 | private static class TestTicker extends Ticker { 77 | 78 | @Override 79 | public Ticks ticks() { 80 | throw new UnsupportedOperationException(); 81 | } 82 | 83 | @Override 84 | public Duration durationBetween(Ticks start, Ticks end) throws IllegalArgumentException { 85 | throw new UnsupportedOperationException(); 86 | } 87 | 88 | public Ticks forTickerValue(long value) { 89 | return createTicks(value); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/TicksTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertNotEquals; 21 | import static org.junit.Assert.assertThrows; 22 | import static org.junit.Assert.assertTrue; 23 | 24 | import com.google.time.client.base.testing.FakeClocks; 25 | import com.google.time.client.base.testing.MoreAsserts; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.junit.runners.JUnit4; 29 | 30 | @RunWith(JUnit4.class) 31 | public class TicksTest { 32 | 33 | private static final Ticker TICKER_1 = new FakeClocks().getFakeTicker(); 34 | private static final Ticker TICKER_2 = new FakeClocks().getFakeTicker(); 35 | 36 | @Test 37 | public void equalsAndHashcode() { 38 | Ticks ticks1_1 = Ticks.fromTickerValue(TICKER_1, 1234L); 39 | Ticks ticks1_2 = Ticks.fromTickerValue(TICKER_1, 1234L); 40 | MoreAsserts.assertComparisonMethods(ticks1_1, ticks1_2); 41 | 42 | Ticks ticks2_1 = Ticks.fromTickerValue(TICKER_2, 1234L); 43 | assertNotEquals(ticks1_1, ticks2_1); 44 | 45 | Ticks ticks1_3 = Ticks.fromTickerValue(TICKER_2, 4321L); 46 | assertNotEquals(ticks1_1, ticks1_3); 47 | } 48 | 49 | private void assertEqualsAndHashcodeMatch(Ticks one, Ticks two) { 50 | assertEquals(one, two); 51 | assertEquals(two, one); 52 | assertEquals(one.hashCode(), two.hashCode()); 53 | } 54 | 55 | @Test 56 | public void durationUntil() { 57 | Ticks floor = Ticks.fromTickerValue(TICKER_1, Long.MIN_VALUE); 58 | Ticks zero = Ticks.fromTickerValue(TICKER_1, 0); 59 | Ticks ceil = Ticks.fromTickerValue(TICKER_1, Long.MAX_VALUE); 60 | 61 | assertThrows(ArithmeticException.class, () -> floor.durationUntil(ceil)); 62 | assertThrows(ArithmeticException.class, () -> ceil.durationUntil(floor)); 63 | assertThrows(ArithmeticException.class, () -> floor.durationUntil(zero)); 64 | assertEquals(Duration.ofNanos(Long.MIN_VALUE), zero.durationUntil(floor)); 65 | 66 | assertEquals(Duration.ofNanos(Long.MAX_VALUE), zero.durationUntil(ceil)); 67 | assertEquals(Duration.ofNanos(-Long.MAX_VALUE), ceil.durationUntil(zero)); 68 | 69 | assertEquals(Duration.ofNanos(0), zero.durationUntil(zero)); 70 | assertEquals(Duration.ofNanos(0), floor.durationUntil(floor)); 71 | assertEquals(Duration.ofNanos(0), ceil.durationUntil(ceil)); 72 | 73 | Ticks differentClock = Ticks.fromTickerValue(TICKER_2, 0); 74 | assertThrows(IllegalArgumentException.class, () -> differentClock.durationUntil(zero)); 75 | 76 | Ticks a = Ticks.fromTickerValue(TICKER_1, 1000); 77 | Ticks b = Ticks.fromTickerValue(TICKER_1, 1001); 78 | 79 | assertEquals(Duration.ofNanos(1), a.durationUntil(b)); 80 | assertEquals(Duration.ofNanos(-1), b.durationUntil(a)); 81 | } 82 | 83 | @Test 84 | public void comparable() { 85 | Ticks ticks1_1 = Ticks.fromTickerValue(TICKER_1, 1L); 86 | Ticks ticks1_2 = Ticks.fromTickerValue(TICKER_1, 2L); 87 | assertTrue(ticks1_1.compareTo(ticks1_2) < 0); 88 | assertTrue(ticks1_2.compareTo(ticks1_1) > 0); 89 | 90 | Ticks ticks2_1 = Ticks.fromTickerValue(TICKER_2, 1L); 91 | assertThrows(ClassCastException.class, () -> ticks2_1.compareTo(ticks1_1)); 92 | assertThrows(ClassCastException.class, () -> ticks1_1.compareTo(ticks2_1)); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/impl/ObjectsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertFalse; 21 | import static org.junit.Assert.assertThrows; 22 | import static org.junit.Assert.assertTrue; 23 | 24 | import java.util.Arrays; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.junit.runners.JUnit4; 28 | 29 | @RunWith(JUnit4.class) 30 | public class ObjectsTest { 31 | 32 | @Test 33 | public void requireNonNull() { 34 | assertThrows(NullPointerException.class, () -> Objects.requireNonNull(null)); 35 | 36 | Object nonNull = new Object(); 37 | assertEquals(nonNull, Objects.requireNonNull(nonNull)); 38 | } 39 | 40 | @Test 41 | public void hash() { 42 | assertEquals(Arrays.hashCode(new Object[] {null}), Objects.hash((Object) null)); 43 | assertEquals(Arrays.hashCode(new Object[] {null, null}), Objects.hash(null, null)); 44 | 45 | Object nonNull = new Object(); 46 | assertEquals(Arrays.hashCode(new Object[] {nonNull}), Objects.hash(nonNull)); 47 | } 48 | 49 | @Test 50 | public void equals() { 51 | assertTrue(Objects.equals(null, null)); 52 | 53 | Object nonNull = new Object(); 54 | assertTrue(Objects.equals(nonNull, nonNull)); 55 | assertFalse(Objects.equals(nonNull, null)); 56 | assertFalse(Objects.equals(null, nonNull)); 57 | } 58 | 59 | @Test 60 | public void testToString() { 61 | assertEquals("null", Objects.toString(null)); 62 | assertEquals("foobar", Objects.toString("foobar")); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/impl/PlatformRandomTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import org.junit.Test; 20 | import org.junit.runner.RunWith; 21 | import org.junit.runners.JUnit4; 22 | 23 | @RunWith(JUnit4.class) 24 | public class PlatformRandomTest { 25 | 26 | @Test 27 | public void doesNotThrow() { 28 | PlatformRandom.getDefaultRandom().nextInt(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/testing/BytesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static org.junit.Assert.assertArrayEquals; 20 | import static org.junit.Assert.assertThrows; 21 | 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | @RunWith(JUnit4.class) 27 | public class BytesTest { 28 | 29 | @Test 30 | public void bytes() { 31 | // These demonstrate how the bytes() method is more compact than Java's often verbose syntax for 32 | // byte literals, and inability to deal with unsigned bytes, which is why the method exists. 33 | assertArrayEquals( 34 | new byte[] { 35 | (byte) 0b10000000, 36 | (byte) 0b10000001, 37 | (byte) 0b11111111, 38 | (byte) 0b00000000, 39 | (byte) 0b00000001, 40 | (byte) 0b01111110, 41 | (byte) 0b01111111, 42 | (byte) 0b10000000, 43 | (byte) 0b11111110, 44 | (byte) 0b11111111, 45 | }, 46 | Bytes.bytes(-128, -127, -1, 0, 1, 126, 127, 128, 254, 255)); 47 | assertArrayEquals( 48 | new byte[] { 49 | -128, -127, -1, 0, 1, 126, 127, (byte) 128, (byte) 254, (byte) 255, 50 | }, 51 | Bytes.bytes(-128, -127, -1, 0, 1, 126, 127, 128, 254, 255)); 52 | 53 | assertThrows(ArithmeticException.class, () -> Bytes.bytes(256)); 54 | assertThrows(ArithmeticException.class, () -> Bytes.bytes(Integer.MAX_VALUE)); 55 | assertThrows(ArithmeticException.class, () -> Bytes.bytes(-129)); 56 | assertThrows(ArithmeticException.class, () -> Bytes.bytes(Integer.MIN_VALUE)); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/testing/DateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertThrows; 21 | 22 | import com.google.time.client.base.Instant; 23 | import org.junit.Test; 24 | import org.junit.runner.RunWith; 25 | import org.junit.runners.JUnit4; 26 | 27 | @RunWith(JUnit4.class) 28 | public class DateTimeUtilsTest { 29 | 30 | @Test 31 | public void utc() { 32 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1899, 1, 1, 0, 0, 0, 0)); 33 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(2101, 1, 1, 0, 0, 0, 0)); 34 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 0, 1, 0, 0, 0, 0)); 35 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 13, 1, 0, 0, 0, 0)); 36 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 0, 0, 0, 0, 0)); 37 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 32, 0, 0, 0, 0)); 38 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, -1, 0, 0, 0)); 39 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 24, 0, 0, 0)); 40 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 0, -1, 0, 0)); 41 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 0, 60, 0, 0)); 42 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 0, 0, -1, 0)); 43 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 0, 0, 60, 0)); 44 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 0, 0, 60, -1)); 45 | assertThrows( 46 | IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 1, 1, 0, 0, 60, 1000000000)); 47 | 48 | // Gregorian calendar validation 49 | assertThrows(IllegalArgumentException.class, () -> DateTimeUtils.utc(1970, 2, 31, 0, 0, 0, 0)); 50 | 51 | // Arbitrary date / times. 52 | assertEquals(Instant.ofEpochSecond(-2208988800L, 0), DateTimeUtils.utc(1900, 1, 1, 0, 0, 0, 0)); 53 | assertEquals(Instant.ofEpochSecond(0, 0), DateTimeUtils.utc(1970, 1, 1, 0, 0, 0, 0)); 54 | assertEquals(Instant.ofEpochSecond(0, 1), DateTimeUtils.utc(1970, 1, 1, 0, 0, 0, 1)); 55 | assertEquals( 56 | Instant.ofEpochSecond(0, 1000000), DateTimeUtils.utc(1970, 1, 1, 0, 0, 0, 1000000)); 57 | assertEquals( 58 | Instant.ofEpochSecond(0, 999999999), DateTimeUtils.utc(1970, 1, 1, 0, 0, 0, 999999999)); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/base/testing/PredictableRandomTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | 21 | import org.junit.Test; 22 | import org.junit.runner.RunWith; 23 | import org.junit.runners.JUnit4; 24 | 25 | @RunWith(JUnit4.class) 26 | public class PredictableRandomTest { 27 | 28 | @Test 29 | public void randomDefault() { 30 | PredictableRandom random = new PredictableRandom(); 31 | assertEquals(1, random.nextInt()); 32 | assertEquals(1, random.nextInt()); 33 | assertEquals(1, random.nextInt()); 34 | assertEquals(1, random.nextInt()); 35 | } 36 | 37 | @Test 38 | public void randomSequence() { 39 | PredictableRandom random = new PredictableRandom(); 40 | random.setIntSequence(1, 2, 3); 41 | assertEquals(1, random.nextInt()); 42 | assertEquals(2, random.nextInt()); 43 | assertEquals(3, random.nextInt()); 44 | assertEquals(1, random.nextInt()); 45 | assertEquals(2, random.nextInt()); 46 | assertEquals(3, random.nextInt()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/sntp/BasicSntpClientTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.sntp; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | import static org.junit.Assert.assertThrows; 20 | import static org.mockito.Mockito.mock; 21 | import static org.mockito.Mockito.when; 22 | 23 | import com.google.time.client.base.Duration; 24 | import com.google.time.client.sntp.impl.SntpClientEngine; 25 | import java.net.UnknownHostException; 26 | import java.util.Collections; 27 | import org.junit.Before; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.JUnit4; 31 | 32 | @RunWith(JUnit4.class) 33 | public class BasicSntpClientTest { 34 | 35 | private SntpClientEngine mockEngine; 36 | private BasicSntpClient client; 37 | 38 | @Before 39 | public void setUp() throws Exception { 40 | mockEngine = mock(SntpClientEngine.class); 41 | client = new BasicSntpClient(mockEngine); 42 | } 43 | 44 | @Test 45 | public void executeQuery_serverLookupFails() throws Exception { 46 | when(mockEngine.executeQuery(null)).thenThrow(new UnknownHostException()); 47 | 48 | assertThrows(UnknownHostException.class, () -> client.executeQuery(null)); 49 | } 50 | 51 | @Test 52 | public void executeQuery() throws Exception { 53 | Duration timeAllowed = Duration.ofSeconds(12, 34); 54 | SntpQueryDebugInfo queryDebugInfo = new SntpQueryDebugInfo(Collections.emptyList()); 55 | SntpQueryResult expectedResult = 56 | SntpQueryResult.success(queryDebugInfo, mock(SntpTimeSignal.class)); 57 | when(mockEngine.executeQuery(timeAllowed)).thenReturn(expectedResult); 58 | 59 | assertEquals(expectedResult, client.executeQuery(timeAllowed)); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/sntp/SntpQueryResultTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp; 18 | 19 | import static com.google.time.client.base.testing.MoreAsserts.assertEqualityMethods; 20 | import static org.junit.Assert.assertEquals; 21 | import static org.junit.Assert.assertNotEquals; 22 | import static org.junit.Assert.assertNull; 23 | import static org.mockito.Mockito.mock; 24 | 25 | import java.net.InetAddress; 26 | import java.util.Collections; 27 | import java.util.List; 28 | import org.junit.Test; 29 | import org.junit.runner.RunWith; 30 | import org.junit.runners.JUnit4; 31 | 32 | @RunWith(JUnit4.class) 33 | public class SntpQueryResultTest { 34 | 35 | @Test 36 | public void success() throws Exception { 37 | InetAddress address1 = InetAddress.getByAddress(new byte[] {1, 1, 1, 1}); 38 | List addresses = Collections.singletonList(address1); 39 | SntpQueryDebugInfo debugInfo = new SntpQueryDebugInfo(addresses); 40 | SntpTimeSignal timeSignal = mock(SntpTimeSignal.class); 41 | SntpQueryResult instance = SntpQueryResult.success(debugInfo, timeSignal); 42 | assertEquals(debugInfo, instance.getQueryDebugInfo()); 43 | assertEquals(SntpQueryResult.TYPE_SUCCESS, instance.getType()); 44 | assertEquals(timeSignal, instance.getTimeSignal()); 45 | assertNull(instance.getException()); 46 | } 47 | 48 | @Test 49 | public void timeAllowedExceeded() throws Exception { 50 | InetAddress address1 = InetAddress.getByAddress(new byte[] {1, 1, 1, 1}); 51 | List addresses = Collections.singletonList(address1); 52 | SntpQueryDebugInfo debugInfo = new SntpQueryDebugInfo(addresses); 53 | SntpQueryResult instance = SntpQueryResult.timeAllowedExceeded(debugInfo); 54 | assertEquals(debugInfo, instance.getQueryDebugInfo()); 55 | assertEquals(SntpQueryResult.TYPE_TIME_ALLOWED_EXCEEDED, instance.getType()); 56 | assertNull(instance.getTimeSignal()); 57 | assertNull(instance.getException()); 58 | } 59 | 60 | // Covers equals(Object), compareTo(Duration) & hashCode() (for equality only). 61 | @Test 62 | public void equals() throws Exception { 63 | InetAddress address1 = InetAddress.getByAddress(new byte[] {1, 1, 1, 1}); 64 | List addresses = Collections.singletonList(address1); 65 | SntpQueryDebugInfo debugInfo = new SntpQueryDebugInfo(addresses); 66 | SntpQueryResult one = SntpQueryResult.timeAllowedExceeded(debugInfo); 67 | 68 | SntpQueryResult two = SntpQueryResult.timeAllowedExceeded(debugInfo); 69 | assertEqualityMethods(one, two); 70 | 71 | SntpQueryResult three = SntpQueryResult.success(debugInfo, mock(SntpTimeSignal.class)); 72 | assertNotEquals(one, three); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/sntp/impl/NtpDateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.impl; 18 | 19 | import static org.junit.Assert.assertEquals; 20 | import static org.junit.Assert.assertThrows; 21 | import static org.junit.Assert.assertTrue; 22 | 23 | import java.util.HashSet; 24 | import java.util.Random; 25 | import java.util.Set; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.junit.runners.JUnit4; 29 | 30 | @RunWith(JUnit4.class) 31 | public class NtpDateTimeUtilsTest { 32 | 33 | @Test 34 | public void randomizeLowestBits() { 35 | Random random = new Random(1); 36 | { 37 | int fractionBits = 0; 38 | assertThrows( 39 | IllegalArgumentException.class, 40 | () -> NtpDateTimeUtils.randomizeLowestBits(random, fractionBits, -1)); 41 | assertThrows( 42 | IllegalArgumentException.class, 43 | () -> NtpDateTimeUtils.randomizeLowestBits(random, fractionBits, 0)); 44 | assertThrows( 45 | IllegalArgumentException.class, 46 | () -> NtpDateTimeUtils.randomizeLowestBits(random, fractionBits, Integer.SIZE)); 47 | assertThrows( 48 | IllegalArgumentException.class, 49 | () -> NtpDateTimeUtils.randomizeLowestBits(random, fractionBits, Integer.SIZE + 1)); 50 | } 51 | 52 | // Check the behavior looks correct from a probabilistic point of view. 53 | for (int input : new int[] {0, 0xFFFFFFFF}) { 54 | for (int bitCount = 1; bitCount < Integer.SIZE; bitCount++) { 55 | int upperBitMask = 0xFFFFFFFF << bitCount; 56 | int expectedUpperBits = input & upperBitMask; 57 | 58 | Set values = new HashSet<>(); 59 | values.add(input); 60 | 61 | int trials = 100; 62 | for (int i = 0; i < trials; i++) { 63 | int outputFractionBits = NtpDateTimeUtils.randomizeLowestBits(random, input, bitCount); 64 | 65 | // Record the output value for later analysis. 66 | values.add(outputFractionBits); 67 | 68 | // Check upper bits did not change. 69 | assertEquals(expectedUpperBits, outputFractionBits & upperBitMask); 70 | } 71 | 72 | // It's possible to be more rigorous here, perhaps with a histogram. As bitCount rises, 73 | // values.size() quickly trend towards the value of trials + 1. For now, this mostly just 74 | // guards against a no-op implementation. 75 | assertTrue(bitCount + ":" + values.size(), values.size() > 1); 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/sntp/impl/NtpMessageTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.impl; 18 | 19 | import static org.junit.Assert.assertArrayEquals; 20 | import static org.junit.Assert.assertEquals; 21 | 22 | import com.google.time.client.base.Duration; 23 | import java.net.DatagramPacket; 24 | import java.net.InetAddress; 25 | import org.junit.Test; 26 | import org.junit.runner.RunWith; 27 | import org.junit.runners.JUnit4; 28 | 29 | @RunWith(JUnit4.class) 30 | public class NtpMessageTest { 31 | 32 | @Test 33 | public void datagramPacket() throws Exception { 34 | NtpHeader sampleHeader = 35 | NtpHeader.Builder.createEmptyV3() 36 | .setLeapIndicator(1) 37 | .setVersionNumber(2) 38 | .setMode(3) 39 | .setStratum(4) 40 | .setPollIntervalExponent(5) 41 | .setPrecisionExponent(-6) 42 | .setRootDelayDuration(Duration.ofSeconds(7, 0)) 43 | .setRootDispersionDuration(Duration.ofSeconds(8, 0)) 44 | .setReferenceIdentifierAsString("9ABC") 45 | .setReferenceTimestamp(Timestamp64.fromString("12345678.9ABCDEF1")) 46 | .setOriginateTimestamp(Timestamp64.fromString("23456789.ABCDEF12")) 47 | .setReceiveTimestamp(Timestamp64.fromString("3456789A.BCDEF123")) 48 | .setTransmitTimestamp(Timestamp64.fromString("456789AB.CDEF1234")) 49 | .build(); 50 | NtpMessage sampleMessage = NtpMessage.create(sampleHeader); 51 | byte[] expectedMessageBytes = sampleMessage.toBytes(); 52 | 53 | InetAddress address = InetAddress.getLoopbackAddress(); 54 | Integer port = 1234; 55 | DatagramPacket datagramPacket = 56 | new DatagramPacket(expectedMessageBytes, expectedMessageBytes.length, address, port); 57 | NtpMessage actualMessage = NtpMessage.fromDatagramPacket(datagramPacket); 58 | NtpHeader actualHeader = actualMessage.getHeader(); 59 | assertEquals(sampleHeader.getLeapIndicator(), actualHeader.getLeapIndicator()); 60 | assertEquals(sampleHeader.getVersionNumber(), actualHeader.getVersionNumber()); 61 | assertEquals(sampleHeader.getMode(), actualHeader.getMode()); 62 | assertEquals(sampleHeader.getStratum(), actualHeader.getStratum()); 63 | assertEquals(sampleHeader.getPollIntervalExponent(), actualHeader.getPollIntervalExponent()); 64 | assertEquals(sampleHeader.getPrecisionExponent(), actualHeader.getPrecisionExponent()); 65 | assertEquals(sampleHeader.getRootDelayDuration(), actualHeader.getRootDelayDuration()); 66 | assertEquals( 67 | sampleHeader.getRootDispersionDuration(), actualHeader.getRootDispersionDuration()); 68 | assertEquals( 69 | sampleHeader.getReferenceIdentifierAsString(), 70 | actualHeader.getReferenceIdentifierAsString()); 71 | assertEquals(sampleHeader.getReferenceTimestamp(), actualHeader.getReferenceTimestamp()); 72 | assertEquals(sampleHeader.getOriginateTimestamp(), actualHeader.getOriginateTimestamp()); 73 | assertEquals(sampleHeader.getReceiveTimestamp(), actualHeader.getReceiveTimestamp()); 74 | assertEquals(sampleHeader.getTransmitTimestamp(), actualHeader.getTransmitTimestamp()); 75 | 76 | DatagramPacket actualDatagramPacket = sampleMessage.toDatagramPacket(address, port); 77 | assertEquals(address, actualDatagramPacket.getAddress()); 78 | assertEquals(port.intValue(), actualDatagramPacket.getPort()); 79 | assertArrayEquals(sampleMessage.toBytes(), actualDatagramPacket.getData()); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationFailureResultTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.sntp.impl; 18 | 19 | import static com.google.time.client.base.testing.Bytes.bytes; 20 | import static org.junit.Assert.assertNotEquals; 21 | 22 | import com.google.time.client.base.testing.MoreAsserts; 23 | import java.net.Inet4Address; 24 | import java.net.InetSocketAddress; 25 | import java.net.UnknownHostException; 26 | import org.junit.Test; 27 | import org.junit.runner.RunWith; 28 | import org.junit.runners.JUnit4; 29 | 30 | @RunWith(JUnit4.class) 31 | public class SntpQueryOperationFailureResultTest { 32 | 33 | @Test 34 | public void equals() throws Exception { 35 | InetSocketAddress address1 = createSocketAddress(1); 36 | NtpMessage message1 = createNtpMessage(1); 37 | int failureIdentifier1 = 1; 38 | Exception exception1 = createException(1); 39 | SntpQueryOperation.FailureResult one = 40 | new SntpQueryOperation.FailureResult(address1, message1, failureIdentifier1, exception1); 41 | 42 | // equals(), hashcode(), etc. 43 | { 44 | SntpQueryOperation.FailureResult other = 45 | new SntpQueryOperation.FailureResult(address1, message1, failureIdentifier1, exception1); 46 | MoreAsserts.assertEqualityMethods(one, other); 47 | } 48 | { 49 | InetSocketAddress address2 = createSocketAddress(2); 50 | SntpQueryOperation.FailureResult other = 51 | new SntpQueryOperation.FailureResult(address2, message1, failureIdentifier1, exception1); 52 | assertNotEquals(one, other); 53 | } 54 | { 55 | NtpMessage message2 = createNtpMessage(2); 56 | SntpQueryOperation.FailureResult other = 57 | new SntpQueryOperation.FailureResult(address1, message2, failureIdentifier1, exception1); 58 | assertNotEquals(one, other); 59 | } 60 | { 61 | int failureIdentifier2 = 2; 62 | SntpQueryOperation.FailureResult other = 63 | new SntpQueryOperation.FailureResult(address1, message1, failureIdentifier2, exception1); 64 | assertNotEquals(one, other); 65 | } 66 | { 67 | Exception exception2 = createException(2); 68 | SntpQueryOperation.FailureResult other = 69 | new SntpQueryOperation.FailureResult(address1, message1, failureIdentifier1, exception2); 70 | assertNotEquals(one, other); 71 | } 72 | } 73 | 74 | private static Exception createException(int i) { 75 | return new Exception("test" + i); 76 | } 77 | 78 | private static NtpMessage createNtpMessage(int i) { 79 | return NtpMessage.create( 80 | NtpHeader.Builder.createEmptyV3() 81 | .setOriginateTimestamp(Timestamp64.fromComponents(i, 0)) 82 | .build()); 83 | } 84 | 85 | private static InetSocketAddress createSocketAddress(int i) throws UnknownHostException { 86 | return new InetSocketAddress(Inet4Address.getByAddress(bytes(216, 239, 35, i)), 123); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /java-time-client.bazelrc: -------------------------------------------------------------------------------- 1 | # bazel's sandbox doesn't like the symlinks from javase/ and android/ to common/ 2 | # Without --spawn_strategy=standalone you'll see errors like 3 | # java.nio.file.NoSuchFileException: java/com/google/time/client/base/DateTimeException.java 4 | # because the sandbox copies the symlinks then can't find what they link to. 5 | build --spawn_strategy=standalone 6 | 7 | -------------------------------------------------------------------------------- /java-time-client.config_template: -------------------------------------------------------------------------------- 1 | # A template for java-time-client.config 2 | # Copy this template, and modify to suit your environment. 3 | JAVA_FORMAT_JAR=${ROOT_DIR}/google-java-format-1.15.0-all-deps.jar 4 | ANDROID_SDK=~/Android/Sdk/ 5 | JDK8=/pathto/jdk8 6 | -------------------------------------------------------------------------------- /javase/.bazelrc: -------------------------------------------------------------------------------- 1 | # Include debug info in the compiled jars 2 | build --javacopt=-g 3 | build --host_javacopt=-g 4 | -------------------------------------------------------------------------------- /javase/WORKSPACE: -------------------------------------------------------------------------------- 1 | load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") 2 | 3 | # BEGIN maven support 4 | http_archive( 5 | name = "rules_jvm_external", 6 | sha256 = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca", 7 | strip_prefix = "rules_jvm_external-4.2", 8 | url = "https://github.com/bazelbuild/rules_jvm_external/archive/4.2.zip", 9 | ) 10 | 11 | load("@rules_jvm_external//:defs.bzl", "maven_install") 12 | 13 | maven_install( 14 | artifacts = [ 15 | # Truth (for tests) 16 | "com.google.truth:truth:1.1.3", 17 | # Mockito (for tests) 18 | "org.mockito:mockito-core:jar:3.0.0", 19 | ], 20 | repositories = [ 21 | "https://maven.google.com", 22 | "https://repo1.maven.org/maven2", 23 | ], 24 | ) 25 | # END maven support 26 | 27 | # BEGIN bazel-common imports 28 | http_archive( 29 | name = "google_bazel_common", 30 | sha256 = "d8aa0ef609248c2a494d5dbdd4c89ef2a527a97c5a87687e5a218eb0b77ff640", 31 | strip_prefix = "bazel-common-4a8d451e57fb7e1efecbf9495587a10684a19eb2", 32 | urls = ["https://github.com/google/bazel-common/archive/4a8d451e57fb7e1efecbf9495587a10684a19eb2.zip"], 33 | ) 34 | # END bazel-common imports 35 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/BUILD.bazel: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "base", 3 | srcs = glob([ 4 | "*.java", 5 | "annotations/*.java", 6 | "impl/*.java", 7 | ]), 8 | visibility = ["//visibility:public"], 9 | ) 10 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/DateTimeException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/DateTimeException.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/InstantSource.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/InstantSource.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/Logger.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Logger.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/Network.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Network.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/NetworkOperationResult.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/NetworkOperationResult.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/PlatformInstantSource.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/PlatformInstantSource.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/PlatformNetwork.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/PlatformNetwork.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/PlatformTicker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | /** 20 | * A {@link Ticker} that provides nanosecond-precision access to Java's {@link System#nanoTime()} 21 | * clock. 22 | */ 23 | public final class PlatformTicker extends Ticker { 24 | 25 | private static final PlatformTicker INSTANCE = new PlatformTicker(); 26 | 27 | public static Ticker instance() { 28 | return INSTANCE; 29 | } 30 | 31 | private PlatformTicker() {} 32 | 33 | @Override 34 | public Ticks ticks() { 35 | return createTicks(System.nanoTime()); 36 | } 37 | 38 | @Override 39 | /*@NonNull*/ public Duration durationBetween(/*@NonNull*/ Ticks start, /*@NonNull*/ Ticks end) { 40 | return Duration.ofNanos(incrementsBetween(start, end)); 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "PlatformTicker"; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/ServerAddress.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/ServerAddress.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/Supplier.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Supplier.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/Ticker.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Ticker.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/Ticks.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/base/Ticks.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/annotations/NonFinalForTesting.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/annotations/NonFinalForTesting.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/annotations/VisibleForTesting.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/annotations/VisibleForTesting.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/ClusteredServiceOperation.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/ClusteredServiceOperation.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/DateTimeConstants.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/DateTimeConstants.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/ExactMath.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/ExactMath.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/NoOpLogger.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/NoOpLogger.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/Objects.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/Objects.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/PlatformRandom.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.impl; 18 | 19 | import java.security.NoSuchAlgorithmException; 20 | import java.security.SecureRandom; 21 | import java.util.Random; 22 | 23 | /** Provides access to a generally suitable default {@link Random} instance. */ 24 | public final class PlatformRandom { 25 | 26 | private static final Random DEFAULT_INSTANCE; 27 | 28 | static { 29 | try { 30 | DEFAULT_INSTANCE = SecureRandom.getInstanceStrong(); 31 | } catch (NoSuchAlgorithmException e) { 32 | // This should not happen. 33 | throw new IllegalStateException(e); 34 | } 35 | } 36 | 37 | private PlatformRandom() {} 38 | 39 | public static Random getDefaultRandom() { 40 | return DEFAULT_INSTANCE; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/impl/SystemStreamLogger.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/impl/SystemStreamLogger.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/Advanceable.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/Advanceable.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/BUILD.bazel: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "testing", 3 | testonly = 1, 4 | srcs = glob(["*.java"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//java/com/google/time/client/base", 8 | "@maven//:junit_junit", 9 | ], 10 | ) 11 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/Bytes.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/Bytes.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/DateTimeUtils.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/DateTimeUtils.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/FakeClocks.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/FakeClocks.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/FakeInstantSource.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/FakeInstantSource.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/FakeTicker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.google.time.client.base.testing; 17 | 18 | import static org.junit.Assert.assertEquals; 19 | 20 | import com.google.time.client.base.Duration; 21 | import com.google.time.client.base.Ticker; 22 | import com.google.time.client.base.Ticks; 23 | import com.google.time.client.base.impl.Objects; 24 | 25 | /** 26 | * A fake {@link Ticker} that can be used for tests. See {@link FakeClocks} for how to obtain an 27 | * instance. This ticker simulates one that increments the tick value every nanosecond. 28 | */ 29 | public final class FakeTicker extends Ticker implements Advanceable { 30 | 31 | private final FakeClocks fakeClocks; 32 | 33 | private long ticksValue; 34 | 35 | FakeTicker(FakeClocks fakeClocks) { 36 | this.fakeClocks = Objects.requireNonNull(fakeClocks); 37 | } 38 | 39 | @Override 40 | public Duration durationBetween(Ticks start, Ticks end) throws IllegalArgumentException { 41 | return Duration.ofNanos(incrementsBetween(start, end)); 42 | } 43 | 44 | @Override 45 | public Ticks ticks() { 46 | ticksValue += fakeClocks.autoAdvanceDuration.toNanos(); 47 | return getCurrentTicks(); 48 | } 49 | 50 | /** Asserts the current ticks value matches the one supplied. Does not auto advance. */ 51 | public void assertCurrentTicks(Ticks actual) { 52 | assertEquals(createTicks(ticksValue), actual); 53 | } 54 | 55 | /** Returns the current ticks value. Does not auto advance. */ 56 | public Ticks getCurrentTicks() { 57 | return createTicks(ticksValue); 58 | } 59 | 60 | /** Returns a ticks value. Does not auto advance. */ 61 | public Ticks ticksForValue(long value) { 62 | return createTicks(value); 63 | } 64 | 65 | /** Sets the current ticks value. Does not auto advance. */ 66 | public void setTicksValue(long ticksValue) { 67 | this.ticksValue = ticksValue; 68 | } 69 | 70 | public void advanceNanos(long nanos) { 71 | // FakeTicker.ticksValue is fixed to nanoseconds. 72 | ticksValue += nanos; 73 | } 74 | 75 | @Override 76 | public void advance(Duration duration) { 77 | advanceNanos(duration.toNanos()); 78 | } 79 | 80 | @Override 81 | public String toString() { 82 | return "FakeTicker{" 83 | + "ticksValue=" 84 | + ticksValue 85 | + ", fakeClocks.autoAdvanceDuration=" 86 | + fakeClocks.autoAdvanceDuration 87 | + '}'; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/MoreAsserts.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/MoreAsserts.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/PredictableRandom.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/base/testing/PredictableRandom.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/base/testing/TestEnvironmentUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base.testing; 18 | 19 | /** 20 | * Methods to support tests that need to have different behaviors under different variant / 21 | * environments. 22 | * 23 | *

This is the Java SE variant of this class. 24 | */ 25 | public final class TestEnvironmentUtils { 26 | 27 | private TestEnvironmentUtils() {} 28 | 29 | /** Returns {@code true} if the test is running the Java SE variant of code. */ 30 | public static boolean isThisJavaSe() { 31 | return true; 32 | } 33 | 34 | /** 35 | * Returns the Java version when the test is running the Java SE variant of code. Throws {@link 36 | * AssertionError} when on Android. 37 | */ 38 | public static int getJavaVersion() { 39 | String specVersion = System.getProperty("java.specification.version"); 40 | if (specVersion.equals("1.8")) { 41 | return 8; 42 | } else { 43 | return Integer.parseInt(specVersion); 44 | } 45 | } 46 | 47 | /** Returns {@code true} if the test is running the Android variant of code. */ 48 | public static boolean isThisAndroid() { 49 | return false; 50 | } 51 | 52 | /** 53 | * Returns the Android API level when the test is running the Android variant of code. Throws 54 | * {@link AssertionError} when on Java SE. 55 | */ 56 | @SuppressWarnings("DoNotCallSuggester") 57 | public static int getAndroidApiLevel() { 58 | throw new AssertionError("This is the Java SE variant"); 59 | } 60 | 61 | /** 62 | * Throws {@link org.junit.AssumptionViolatedException} if running the Android variant of code 63 | * under robolectric. 64 | */ 65 | public static void assumeNotRobolectric(String reason) { 66 | // This is the javase variant of this class, so by definition this assumption holds true. 67 | } 68 | 69 | /** Returns {@code true} if running the Android variant of code under robolectric. */ 70 | public static boolean isThisRobolectric() { 71 | // This is the javase variant of this class, so by definition this is false. 72 | return false; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//tools/javadoc:javadoc.bzl", "javadoc_library") 2 | 3 | java_library( 4 | name = "sntp", 5 | srcs = glob([ 6 | "*.java", 7 | "impl/*.java", 8 | ]), 9 | visibility = ["//visibility:public"], 10 | deps = [ 11 | "//java/com/google/time/client/base", 12 | "@maven//:com_google_errorprone_error_prone_annotations", 13 | ], 14 | ) 15 | 16 | javadoc_library( 17 | name = "sntp.javadocs", 18 | srcs = glob(["*.java"]), 19 | deps = [":sntp"], 20 | ) 21 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/BasicSntpClient.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/BasicSntpClient.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/InvalidNtpValueException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/InvalidNtpValueException.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/NtpProtocolException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/NtpProtocolException.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/NtpServerNotReachableException.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/NtpServerNotReachableException.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/SntpClient.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpClient.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/SntpQueryDebugInfo.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpQueryDebugInfo.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/SntpQueryResult.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpQueryResult.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/SntpTimeSignal.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/java/com/google/time/client/sntp/SntpTimeSignal.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/Duration64.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/Duration64.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/NtpDateTimeUtils.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/NtpDateTimeUtils.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/NtpHeader.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/NtpHeader.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/NtpMessage.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/NtpMessage.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SerializationUtils.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SerializationUtils.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SntpClientEngine.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpClientEngine.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SntpQueryOperation.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpQueryOperation.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SntpRequestFactory.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpRequestFactory.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SntpServiceConnector.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpServiceConnector.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SntpServiceConnectorImpl.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpServiceConnectorImpl.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/SntpTimeSignalImpl.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/SntpTimeSignalImpl.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/impl/Timestamp64.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/impl/Timestamp64.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/testing/BUILD.bazel: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "testing", 3 | testonly = 1, 4 | srcs = glob(["*.java"]), 5 | visibility = ["//visibility:public"], 6 | deps = [ 7 | "//java/com/google/time/client/base", 8 | "//java/com/google/time/client/base/testing", 9 | "//java/com/google/time/client/sntp", 10 | "@maven//:junit_junit", 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/testing/FakeNetwork.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/FakeNetwork.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/testing/FakeSntpServerEngine.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/FakeSntpServerEngine.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/testing/SntpTestServer.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/SntpTestServer.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/testing/TestSntpServerEngine.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/TestSntpServerEngine.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/testing/TestSntpServerWithNetwork.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/java/com/google/time/client/sntp/testing/TestSntpServerWithNetwork.java -------------------------------------------------------------------------------- /javase/java/com/google/time/client/sntp/tools/BUILD.bazel: -------------------------------------------------------------------------------- 1 | java_library( 2 | name = "tools", 3 | srcs = glob(["*.java"]), 4 | visibility = ["//visibility:public"], 5 | deps = [ 6 | "//java/com/google/time/client/base", 7 | "//java/com/google/time/client/sntp", 8 | ], 9 | ) 10 | 11 | java_binary( 12 | name = "sntp", 13 | args = ["time.google.com"], 14 | main_class = "com.google.time.client.sntp.tools.SntpTool", 15 | runtime_deps = [":tools"], 16 | ) 17 | 18 | java_binary( 19 | name = "sntp_comp", 20 | args = [ 21 | "time.google.com", 22 | "time.android.com", 23 | "pool.ntp.org", 24 | "uk.pool.ntp.org", 25 | "cn.pool.ntp.org", 26 | # From https://timetoolsltd.com/information/public-ntp-server/uk/ 27 | "ntp.my-inbox.co.uk", 28 | "ntp1.npl.co.uk", 29 | "ntp2.npl.co.uk", 30 | "ntp1.ja.net", 31 | "ntp2.ja.net", 32 | "ntp.virginmedia.com", 33 | "ntp2d.mcc.ac.uk", 34 | "ntp2c.mcc.ac.uk", 35 | "ntp.exnet.com", 36 | "ntp0.csx.cam.ac.uk", 37 | "ntp1.csx.cam.ac.uk", 38 | "ntp2.csx.cam.ac.uk", 39 | "ntp.cis.strath.ac.uk", 40 | "ntppub.le.ac.uk", 41 | # From https://gist.github.com/mutin-sa/eea1c396b1e610a2da1e5550d94b0453 42 | "time.cloudflare.com", 43 | "time.facebook.com", 44 | "time.windows.com", 45 | "time.apple.com", 46 | "time.nist.gov", 47 | ], 48 | main_class = "com.google.time.client.sntp.tools.SntpComparisonTool", 49 | runtime_deps = [":tools"], 50 | ) 51 | -------------------------------------------------------------------------------- /javase/javase.bazelproject: -------------------------------------------------------------------------------- 1 | directories: 2 | java 3 | javatests 4 | targets: 5 | //java/com/google/time/client/... 6 | //javatests/com/google/time/client/... 7 | workspace_type: java 8 | java_language_level: 8 9 | test_sources: 10 | javatests/* 11 | -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//testing:test_defs.bzl", "gen_java_tests") 2 | 3 | gen_java_tests( 4 | name = "tests", 5 | srcs = glob([ 6 | "*.java", 7 | "impl/*.java", 8 | ]), 9 | deps = [ 10 | "//java/com/google/time/client/base", 11 | "//java/com/google/time/client/base/testing", 12 | "@maven//:com_google_truth_truth", 13 | "@maven//:junit_junit", 14 | "@maven//:org_mockito_mockito_core", 15 | ], 16 | ) 17 | -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/DurationTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/DurationTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/InstantTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/InstantTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/NetworkOperationResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/NetworkOperationResultTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/PlatformInstantSourceTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/PlatformInstantSourceTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/PlatformNetworkTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/PlatformNetworkTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/PlatformTickerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.google.time.client.base; 18 | 19 | import static com.google.time.client.base.impl.DateTimeConstants.NANOS_PER_MILLISECOND; 20 | import static org.junit.Assert.assertTrue; 21 | 22 | import org.junit.Test; 23 | import org.junit.runner.RunWith; 24 | import org.junit.runners.JUnit4; 25 | 26 | @RunWith(JUnit4.class) 27 | public class PlatformTickerTest { 28 | 29 | @Test 30 | public void ticksAndDurationBetween() throws Exception { 31 | Ticker ticker = PlatformTicker.instance(); 32 | 33 | long before1 = System.nanoTime(); 34 | Ticks tick1 = ticker.ticks(); 35 | long after1 = System.nanoTime(); 36 | 37 | Thread.sleep(250); 38 | 39 | long before2 = System.nanoTime(); 40 | Ticks tick2 = ticker.ticks(); 41 | long after2 = System.nanoTime(); 42 | 43 | Duration maxDuration = Duration.ofNanos(after2 - before1); 44 | Duration minDuration = Duration.ofNanos(before2 - after1); 45 | Duration durationBetweenTicks = tick1.durationUntil(tick2); 46 | 47 | assertTrue(durationBetweenTicks.compareTo(minDuration) >= 0); 48 | assertTrue(durationBetweenTicks.compareTo(maxDuration) <= 0); 49 | } 50 | 51 | @Test 52 | public void ticksPrecision() { 53 | Ticker ticker = PlatformTicker.instance(); 54 | 55 | // Try to prove that the ticker is precise below millis. 56 | Ticks ticks1 = ticker.ticks(); 57 | Ticks ticks2 = ticker.ticks(); 58 | Ticks ticks3 = ticker.ticks(); 59 | assertTrue( 60 | durationUntilHasNonZeroNanos(ticks1, ticks2) 61 | || durationUntilHasNonZeroNanos(ticks1, ticks3)); 62 | } 63 | 64 | private static boolean durationUntilHasNonZeroNanos(Ticks ticks1, Ticks ticks2) { 65 | return ticks1.durationUntil(ticks2).getNano() % NANOS_PER_MILLISECOND != 0; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/TickerTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/TickerTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/TicksTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/base/TicksTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/impl/ClusteredServiceOperationTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/impl/ClusteredServiceOperationTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/impl/ObjectsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/impl/ObjectsTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/impl/PlatformRandomTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/impl/PlatformRandomTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/testing/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//testing:test_defs.bzl", "gen_java_tests") 2 | 3 | gen_java_tests( 4 | name = "tests", 5 | srcs = glob(["*.java"]), 6 | deps = [ 7 | "//java/com/google/time/client/base", 8 | "//java/com/google/time/client/base/testing", 9 | "@maven//:com_google_truth_truth", 10 | "@maven//:junit_junit", 11 | ], 12 | ) 13 | -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/testing/BytesTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/BytesTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/testing/DateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/DateTimeUtilsTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/testing/FakeClocksTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/FakeClocksTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/base/testing/PredictableRandomTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/base/testing/PredictableRandomTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/BUILD.bazel: -------------------------------------------------------------------------------- 1 | load("@google_bazel_common//testing:test_defs.bzl", "gen_java_tests") 2 | 3 | gen_java_tests( 4 | name = "tests", 5 | srcs = glob([ 6 | "*.java", 7 | "impl/*.java", 8 | ]), 9 | deps = [ 10 | "//java/com/google/time/client/base", 11 | "//java/com/google/time/client/base/testing", 12 | "//java/com/google/time/client/sntp", 13 | "//java/com/google/time/client/sntp/testing", 14 | "@maven//:com_google_truth_truth", 15 | "@maven//:junit_junit", 16 | "@maven//:org_mockito_mockito_core", 17 | ], 18 | ) 19 | -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/BasicSntpClientTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/sntp/BasicSntpClientTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/SntpQueryDebugInfoTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/sntp/SntpQueryDebugInfoTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/SntpQueryResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../common/javatests/com/google/time/client/sntp/SntpQueryResultTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/Duration64Test.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/Duration64Test.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/NtpDateTimeUtilsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/NtpDateTimeUtilsTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/NtpHeaderTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/NtpHeaderTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/NtpMessageTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/NtpMessageTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SerializationUtilsTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SerializationUtilsTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpClientEngineNetworkingTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpClientEngineNetworkingTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpClientEngineUnitTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpClientEngineUnitTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpQueryOperationFailureResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationFailureResultTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpQueryOperationSuccessResultTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationSuccessResultTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpQueryOperationTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpQueryOperationTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpRequestFactoryTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpRequestFactoryTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/SntpTimeSignalImplTest.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/SntpTimeSignalImplTest.java -------------------------------------------------------------------------------- /javase/javatests/com/google/time/client/sntp/impl/Timestamp64Test.java: -------------------------------------------------------------------------------- 1 | ../../../../../../../../common/javatests/com/google/time/client/sntp/impl/Timestamp64Test.java -------------------------------------------------------------------------------- /reformat-java.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # Invokes the google-java-format tool. 17 | 18 | PROJECT_ROOT=`dirname $0` 19 | 20 | GOOGLE_JAVA_FORMAT=${1} 21 | if [[ -z ${GOOGLE_JAVA_FORMAT} ]]; then 22 | echo "Usage: ${0} " 23 | exit 1 24 | fi 25 | 26 | find ${PROJECT_ROOT} -name "*.java" | xargs java -jar ${GOOGLE_JAVA_FORMAT} -r 27 | 28 | -------------------------------------------------------------------------------- /regenerate-common-symlinks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # Deletes all symlinks to under android/ and javase/ and generates symlinks from 17 | # those directories to files under common/. This is the main script developers 18 | # should run to keep the symlinks under android/ and javase/ directories 19 | # correct. 20 | 21 | PROJECT_ROOT=`dirname $0` 22 | 23 | find ${PROJECT_ROOT}/android -type l | xargs rm 24 | find ${PROJECT_ROOT}/javase -type l | xargs rm 25 | 26 | COMMON_FILES_INFO=$(find ${PROJECT_ROOT}/common -type f -printf "%d|%f|%h|%H|%p|%P\n") 27 | for FILE_INFO in ${COMMON_FILES_INFO}; do 28 | IFS="|" read -a FILE_INFO_ARR <<< ${FILE_INFO} 29 | DEPTH=${FILE_INFO_ARR[0]} 30 | PARENT_PATH=$(printf '../%.0s' $(eval echo {1..${DEPTH}})) 31 | RELATIVE_FILE=${FILE_INFO_ARR[5]} 32 | echo Adding symlinks for ${RELATIVE_FILE} 33 | ln -s ${PARENT_PATH}common/${RELATIVE_FILE} ${PROJECT_ROOT}/android/${RELATIVE_FILE} 34 | ln -s ${PARENT_PATH}common/${RELATIVE_FILE} ${PROJECT_ROOT}/javase/${RELATIVE_FILE} 35 | done 36 | -------------------------------------------------------------------------------- /replace-symlinks-to-common-with-copies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # Creates copies of files from common rather than symlinks. 17 | # Be careful! This is useful for working with tooling that doesn't like 18 | # symlinks such as coverage tools. 19 | # Use rm-copies-of-common.sh to remove (exact) copies again and 20 | # regenerate-common-symlinks.sh to regenerate the symlinks. 21 | 22 | PROJECT_ROOT=`dirname $0` 23 | 24 | find ${PROJECT_ROOT}/android -type l | xargs rm 25 | find ${PROJECT_ROOT}/javase -type l | xargs rm 26 | 27 | COMMON_FILES_INFO=$(find ${PROJECT_ROOT}/common -type f -printf "%d|%f|%h|%H|%p|%P\n") 28 | for FILE_INFO in ${COMMON_FILES_INFO}; do 29 | IFS="|" read -a FILE_INFO_ARR <<< ${FILE_INFO} 30 | RELATIVE_FILE=${FILE_INFO_ARR[5]} 31 | echo Copying ${RELATIVE_FILE} 32 | cp ${PROJECT_ROOT}/common/${RELATIVE_FILE} ${PROJECT_ROOT}/android/${RELATIVE_FILE} 33 | cp ${PROJECT_ROOT}/common/${RELATIVE_FILE} ${PROJECT_ROOT}/javase/${RELATIVE_FILE} 34 | done 35 | -------------------------------------------------------------------------------- /rm-copies-of-common.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2022 Google LLC 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This script is used to remove copies of files from common/ that exist in in 17 | # android/ and javase/. This is typically used to undo copies created with 18 | # replace-symlinks-to-common-with-copies.sh. If files exist in a variant but 19 | # differ, this is reported and the variant copy is kept. 20 | 21 | function delete_if_same_as() { 22 | F1=$1 23 | F2=$2 24 | 25 | if [[ ! -a ${F1} ]]; then return; fi 26 | 27 | diff ${F1} ${F2} > /dev/null 28 | if (( $? == 0 )); then 29 | echo Deleting ${F1} 30 | rm ${F1} 31 | else 32 | echo ${F1} differs from ${F2} Skipping 33 | fi 34 | } 35 | 36 | PROJECT_ROOT=`dirname $0` 37 | 38 | COMMON_FILES_INFO=$(find ${PROJECT_ROOT}/common -type f -printf "%d|%f|%h|%H|%p|%P\n") 39 | for FILE_INFO in ${COMMON_FILES_INFO}; do 40 | IFS="|" read -a FILE_INFO_ARR <<< ${FILE_INFO} 41 | RELATIVE_FILE=${FILE_INFO_ARR[5]} 42 | delete_if_same_as ${PROJECT_ROOT}/android/${RELATIVE_FILE} ${PROJECT_ROOT}/common/${RELATIVE_FILE} 43 | delete_if_same_as ${PROJECT_ROOT}/javase/${RELATIVE_FILE} ${PROJECT_ROOT}/common/${RELATIVE_FILE} 44 | done 45 | --------------------------------------------------------------------------------