package model.asn1; import model.asn1.exceptions.ParseException; import model.asn1.parsing.BytesReader; import org.junit.jupiter.api.Test; import java.time.ZoneId; import java.time.ZonedDateTime; import static org.junit.jupiter.api.Assertions.*; public class GeneralizedTimeTest { @Test void testConstructor() throws ParseException { final ZonedDateTime now = ZonedDateTime.now(ZoneId.of("UTC")); assertEquals(now, new GeneralizedTime(GeneralizedTime.TAG, null, now).getTimestamp()); final ASN1Time parsed = new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '1', '9', '1', '9', '0', '8', '1', '0', '1', '1', '4', '5', '1', '4', 'Z' }), false); assertEquals("19190810114514Z", parsed.toString()); assertEquals(ZonedDateTime.of(1919, 8, 10, 11, 45, 14, 0, ZoneId.of("UTC")), parsed.getTimestamp()); } @Test void testParse() throws ParseException { ASN1Time parsed = new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', '1', '4', 'Z' }), false); assertEquals(ZonedDateTime.of(2023, 9, 27, 11, 45, 14, 0, ZoneId.of("UTC")), parsed.getTimestamp()); // No seconds parsed = new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 13, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', 'Z' }), false); assertEquals(ZonedDateTime.of(2023, 9, 27, 11, 45, 0, 0, ZoneId.of("UTC")), parsed.getTimestamp()); // Length 0 assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 0 }), false)); // Early EOF assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15 }), false)); // No tailing Z assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 14, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', '1', '4' }), false)); // Custom timezone assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 18, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', '1', '4', 'Z', '-', '0', '8' }), false)); // Invalid month / day / hour / minute / second assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '2', '0', '2', '3', '1', '3', '2', '7', '1', '1', '4', '5', '1', '4', 'Z' }), false)); assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '2', '0', '2', '3', '1', '0', '3', '2', '1', '1', '4', '5', '1', '4', 'Z' }), false)); assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '2', '0', '2', '3', '1', '0', '3', '0', '2', '5', '4', '5', '1', '4', 'Z' }), false)); assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '2', '0', '2', '3', '1', '0', '3', '0', '2', '4', '6', '1', '1', '4', 'Z' }), false)); assertThrows(ParseException.class, () -> new GeneralizedTime(new BytesReader(new Byte[]{ 0x18, 15, '2', '0', '2', '3', '1', '0', '3', '0', '2', '4', '6', '0', '6', '1', 'Z' }), false)); } @Test void testEncode() throws ParseException { assertEquals("20230927114514Z", new GeneralizedTime(new BytesReader(new Byte[]{ -95, 17, 0x18, 15, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', '1', '4', 'Z' }), true).toString()); // No seconds assertEquals("202309271145Z", new GeneralizedTime(new BytesReader(new Byte[]{ -95, 15, 0x18, 13, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', 'Z' }), true).toString()); // To byte array assertArrayEquals(new Byte[]{ 0x18, 13, '2', '0', '2', '3', '0', '9', '2', '7', '1', '1', '4', '5', 'Z' }, new GeneralizedTime(GeneralizedTime.TAG, null, ZonedDateTime.of(2023, 9, 27, 11, 45, 0, 0, ZoneId.of("UTC"))) .encodeDER()); } }