Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ slf4j-version = "2.0.16"
slf4j-v1x-version = "1.7.36"
crt-kotlin-version = "0.8.10"
micrometer-version = "1.13.6"
kotlinx-datetime-version = "0.6.1"

# codegen
smithy-version = "1.51.0"
Expand Down Expand Up @@ -61,6 +62,7 @@ slf4j-api-v1x = { module = "org.slf4j:slf4j-api", version.ref = "slf4j-v1x-versi
slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j-version" }
crt-kotlin = { module = "aws.sdk.kotlin.crt:aws-crt-kotlin", version.ref = "crt-kotlin-version" }
micrometer-core = { module = "io.micrometer:micrometer-core", version.ref = "micrometer-version" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime-version" }

smithy-codegen-core = { module = "software.amazon.smithy:smithy-codegen-core", version.ref = "smithy-version" }
smithy-cli = { module = "software.amazon.smithy:smithy-cli", version.ref = "smithy-version" }
Expand Down
1 change: 1 addition & 0 deletions runtime/runtime-core/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ kotlin {
nativeMain {
dependencies {
api(libs.crt.kotlin)
implementation(libs.kotlinx.datetime)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ package aws.smithy.kotlin.runtime.time
*/
public enum class TimestampFormat {
/**
* ISO-8601/RFC5399 timestamp including fractional seconds at microsecond precision (e.g.,
* ISO-8601/RFC3339 timestamp including fractional seconds at microsecond precision (e.g.,
* "2022-04-25T16:44:13.667307Z")
*
* Prefers RFC5399 when formatting
* Prefers RFC3339 when formatting
Comment on lines -12 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment: Oh jeez, good catch. 🤦‍♂️

*/
ISO_8601,

Expand All @@ -28,7 +28,7 @@ public enum class TimestampFormat {
ISO_8601_CONDENSED_DATE,

/**
* ISO-8601/RFC5399 timestamp including fractional seconds at arbitrary (i.e., untruncated) precision
* ISO-8601/RFC3339 timestamp including fractional seconds at arbitrary (i.e., untruncated) precision
*/
ISO_8601_FULL,

Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Question: Because of some of the refactoring, it's a bit tricky for me to see what's functionally changed in these tests. Besides the addition of .fromEpochSeconds(${test.sec}, ${test.ns}) to an assert message, what's changed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing else changed, it's just restructured

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
*/
package aws.smithy.kotlin.runtime.time

import aws.smithy.kotlin.runtime.IgnoreNative
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
Expand All @@ -18,7 +17,6 @@ import kotlin.time.Duration.Companion.seconds
// tests for conversion from a parsed representation into an Instant instance

class InstantTest {

/**
* Conversion from a string to epoch sec/ns
*/
Expand Down Expand Up @@ -58,11 +56,8 @@ class InstantTest {

// leap second - dropped to: 2020-12-31T23:59:59
FromTest("2020-12-31T23:59:60Z", 1609459199, 0),
// midnight - should be 11/5 12AM
FromTest("2020-11-04T24:00:00Z", 1604534400, 0),
)

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testFromIso8601() {
for ((idx, test) in iso8601Tests.withIndex()) {
Expand Down Expand Up @@ -101,7 +96,6 @@ class InstantTest {
TimestampFormat.ISO_8601_CONDENSED_DATE to Iso8601FmtTest::expectedIso8601CondDate,
)

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testFormatAsIso8601() {
for ((idx, test) in iso8601FmtTests.withIndex()) {
Expand All @@ -110,7 +104,7 @@ class InstantTest {
.fromEpochSeconds(test.sec, test.ns)
.format(format)
val expected = getter(test)
assertEquals(expected, actual, "test[$idx]: failed to correctly format Instant as $format")
assertEquals(expected, actual, "test[$idx]: failed to correctly format Instant.fromEpochSeconds(${test.sec}, ${test.ns}) as $format")
}
}
}
Expand All @@ -125,7 +119,6 @@ class InstantTest {
FromTest("Thu, 05 Nov 2020 19:22:37 -1245", 1604650057, 0),
)

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testFromRfc5322() {
for ((idx, test) in rfc5322Tests.withIndex()) {
Expand All @@ -143,7 +136,6 @@ class InstantTest {
FmtTest(1604650057, 0, "Fri, 06 Nov 2020 08:07:37 GMT"),
)

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testFormatAsRfc5322() {
for ((idx, test) in rfc5322FmtTests.withIndex()) {
Expand All @@ -162,7 +154,6 @@ class InstantTest {
FmtTest(1604604157, 345_006_000, "1604604157.345006"),
)

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testFormatAsEpochSeconds() {
for ((idx, test) in epochFmtTests.withIndex()) {
Expand All @@ -173,7 +164,6 @@ class InstantTest {
}
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testToEpochDouble() {
val sec = 1604604157L
Expand All @@ -184,7 +174,6 @@ class InstantTest {
assertTrue(kotlin.math.abs(0.012345 - fracSecs) < 0.00001)
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testGetCurrentTime() {
val currentTime = Instant.now()
Expand All @@ -194,7 +183,6 @@ class InstantTest {
assertTrue(currentTime.epochSeconds > pastInstant)
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testGetEpochMilliseconds() {
val instant = Instant.fromEpochSeconds(1602878160, 200_000)
Expand All @@ -206,7 +194,6 @@ class InstantTest {
assertEquals(expected2, instantWithMilli.epochMilliseconds)
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testFromEpochMilliseconds() {
val ts1 = 1602878160000L
Expand All @@ -218,54 +205,34 @@ class InstantTest {
assertEquals(expected2, Instant.fromEpochMilliseconds(ts2))
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testNegativeFromEpochSeconds() {
val timestamp = Instant.fromEpochSeconds(-806976000L)
assertEquals("1944-06-06T00:00:00Z", timestamp.toString())
}

// Select tests pulled from edge cases/tickets in the V2 Java SDK.
// Always good to learn from others...
class V2JavaSdkTests {
@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun v2JavaSdkTt0031561767() {
val input = "Fri, 16 May 2014 23:56:46 GMT"
val instant: Instant = Instant.fromRfc5322(input)
assertEquals(input, instant.format(TimestampFormat.RFC_5322))
}
@Test
fun testUntil() {
val untilTests = mapOf(
("2013-01-01T00:00:00+00:00" to "2014-01-01T00:00:00+00:00") to 365.days,
("2020-01-01T00:00:00+00:00" to "2021-01-01T00:00:00+00:00") to 366.days, // leap year!
("2023-10-06T00:00:00+00:00" to "2023-10-06T00:00:00+00:00") to Duration.ZERO,
("2023-10-06T00:00:00+00:00" to "2023-10-07T00:00:00+00:00") to 1.days,
("2023-10-06T00:00:00+00:00" to "2023-10-06T01:00:00+00:00") to 1.hours,
("2023-10-06T00:00:00+00:00" to "2023-10-06T00:01:00+00:00") to 1.minutes,
("2023-10-06T00:00:00+00:00" to "2023-10-06T00:00:01+00:00") to 1.seconds,
("2023-10-06T00:00:00+00:00" to "2023-10-06T12:12:12+00:00") to 12.hours + 12.minutes + 12.seconds,
)

/**
* Tests the Date marshalling and unmarshalling. Asserts that the value is
* same before and after marshalling/unmarshalling
*/
@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun v2JavaSdkUnixTimestampRoundtrip() {
// v2 sdk used currentTimeMillis(), instead we just hard code a value here
// otherwise that would be a JVM specific test since since we do not (yet) have
// a Kotlin MPP way of getting current timestamp. Also obviously not using epoch mill
// but instead just epoch sec. Spirit of the test is the same though
longArrayOf(1595016457, 1L, 0L)
.map { Instant.fromEpochSeconds(0, 0) }
.forEach { instant ->
val serverSpecificDateFormat: String = instant.format(TimestampFormat.EPOCH_SECONDS)
val parsed: Instant = parseEpoch(serverSpecificDateFormat)
assertEquals(instant.epochSeconds, parsed.epochSeconds)
}
}
for ((times, expectedDuration) in untilTests) {
val start = Instant.fromIso8601(times.first)
val end = Instant.fromIso8601(times.second)

// NOTE: There is additional set of edge case tests related to a past issue
// in DateUtilsTest.java in the v2 sdk. Specifically around
// issue 223: https://github.com/aws/aws-sdk-java/issues/233
//
// (1) - That issue is about round tripping values between SDK versions
// (2) - The input year in those tests is NOT valid and should never have
// been accepted by the parser.
assertEquals(expectedDuration, start.until(end))
assertEquals(end.until(start), -expectedDuration)
}
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testPlusMinusDuration() {
val start = Instant.fromEpochSeconds(1000, 1000)
Expand All @@ -275,7 +242,6 @@ class InstantTest {
assertEquals(Instant.fromEpochSeconds(990, 0), start - offset)
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
@Test
fun testRoundTripUtcOffset() {
// sanity check we only ever emit UTC timestamps (e.g. round trip a response with UTC offset)
Expand All @@ -293,27 +259,42 @@ class InstantTest {
assertEquals(test.second, actual, "test[$idx]: failed to format offset timestamp in UTC")
}
}
}

@IgnoreNative // FIXME Re-enable after Kotlin/Native implementation
// Select tests pulled from edge cases/tickets in the V2 Java SDK.
// Always good to learn from others...
class V2JavaSdkTests {
@Test
fun testUntil() {
val untilTests = mapOf(
("2013-01-01T00:00:00+00:00" to "2014-01-01T00:00:00+00:00") to 365.days,
("2020-01-01T00:00:00+00:00" to "2021-01-01T00:00:00+00:00") to 366.days, // leap year!
("2023-10-06T00:00:00+00:00" to "2023-10-06T00:00:00+00:00") to Duration.ZERO,
("2023-10-06T00:00:00+00:00" to "2023-10-07T00:00:00+00:00") to 1.days,
("2023-10-06T00:00:00+00:00" to "2023-10-06T01:00:00+00:00") to 1.hours,
("2023-10-06T00:00:00+00:00" to "2023-10-06T00:01:00+00:00") to 1.minutes,
("2023-10-06T00:00:00+00:00" to "2023-10-06T00:00:01+00:00") to 1.seconds,
("2023-10-06T00:00:00+00:00" to "2023-10-06T12:12:12+00:00") to 12.hours + 12.minutes + 12.seconds,
)

for ((times, expectedDuration) in untilTests) {
val start = Instant.fromIso8601(times.first)
val end = Instant.fromIso8601(times.second)
fun v2JavaSdkTt0031561767() {
val input = "Fri, 16 May 2014 23:56:46 GMT"
val instant: Instant = Instant.fromRfc5322(input)
assertEquals(input, instant.format(TimestampFormat.RFC_5322))
}

assertEquals(expectedDuration, start.until(end))
assertEquals(end.until(start), -expectedDuration)
}
/**
* Tests the Date marshalling and unmarshalling. Asserts that the value is
* same before and after marshalling/unmarshalling
*/
@Test
fun v2JavaSdkUnixTimestampRoundtrip() {
// v2 sdk used currentTimeMillis(), instead we just hard code a value here
// otherwise that would be a JVM specific test since since we do not (yet) have
// a Kotlin MPP way of getting current timestamp. Also obviously not using epoch mill
// but instead just epoch sec. Spirit of the test is the same though
longArrayOf(1595016457, 1L, 0L)
.map { Instant.fromEpochSeconds(0, 0) }
.forEach { instant ->
val serverSpecificDateFormat: String = instant.format(TimestampFormat.EPOCH_SECONDS)
val parsed: Instant = parseEpoch(serverSpecificDateFormat)
assertEquals(instant.epochSeconds, parsed.epochSeconds)
}
}

// NOTE: There is additional set of edge case tests related to a past issue
// in DateUtilsTest.java in the v2 sdk. Specifically around
// issue 223: https://github.com/aws/aws-sdk-java/issues/233
//
// (1) - That issue is about round tripping values between SDK versions
// (2) - The input year in those tests is NOT valid and should never have
// been accepted by the parser.
}
Loading
Loading