001/* 002 * Copyright 2015 SirWellington Tech. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANYTIME KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package tech.sirwellington.alchemy.test.junit.runners; 018 019import java.lang.annotation.Retention; 020import java.lang.annotation.Target; 021import java.time.Instant; 022import tech.sirwellington.alchemy.annotations.access.Internal; 023import tech.sirwellington.alchemy.annotations.access.NonInstantiable; 024import tech.sirwellington.alchemy.generator.AlchemyGenerator; 025import tech.sirwellington.alchemy.generator.TimeGenerators; 026 027import static java.lang.annotation.ElementType.FIELD; 028import static java.lang.annotation.RetentionPolicy.RUNTIME; 029import static tech.sirwellington.alchemy.test.Checks.Internal.checkNotNull; 030import static tech.sirwellington.alchemy.test.Checks.Internal.checkThat; 031 032/** 033 * Used in with the {@link AlchemyTestRunner}, this Annotations allows the Runtime Injection of 034 * Generated {@linkplain Instant Instants} using {@link TimeGenerators} from the {@link AlchemyGenerator} library. 035 * 036 * Example: 037 * <pre> 038 * {@code 039 * `@RunWith(AlchemyTestRunner.class) 040 * public class ExampleTest 041 * { 042 * `@GenerateInstant(ANYTIME) 043 * private Instant timeOfOrder; 044 * 045 * ... 046 * } 047 * } 048 * </pre> 049 * Note, ticks (`) used to escape Javadocs. 050 * 051 * @see GenerateString 052 * @see GenerateDate 053 * 054 * @author SirWellington 055 */ 056@Target(FIELD) 057@Retention(RUNTIME) 058public @interface GenerateInstant 059{ 060 061 Type value() default Type.ANYTIME; 062 063 /** 064 * If using the {@link Type#RANGE} type, specify a beginning time, in Epoch Millis. 065 * 066 * @return 067 */ 068 long startTime() default 0; 069 070 /** 071 * If using the {@link Type#RANGE} type, specify an end time, in Epoch Millis. 072 * 073 * @return 074 */ 075 long endTime() default 0; 076 077 public enum Type 078 { 079 PAST, 080 PRESENT, 081 FUTURE, 082 ANYTIME, 083 RANGE 084 } 085 086 @Internal 087 @NonInstantiable 088 static class Values 089 { 090 091 private Values() throws IllegalAccessException 092 { 093 throw new IllegalAccessException("cannot instantiate"); 094 } 095 096 static AlchemyGenerator<Instant> createGeneratorFor(GenerateInstant annotation) throws IllegalArgumentException 097 { 098 checkNotNull(annotation, "missing annotation"); 099 100 switch (annotation.value()) 101 { 102 case PAST: 103 return TimeGenerators.pastInstants(); 104 case PRESENT: 105 return TimeGenerators.presentInstants(); 106 case FUTURE: 107 return TimeGenerators.futureInstants(); 108 case ANYTIME: 109 return TimeGenerators.anytime(); 110 case RANGE: 111 return timesInRange(annotation.startTime(), annotation.endTime()); 112 default: 113 return TimeGenerators.anytime(); 114 } 115 } 116 117 private static AlchemyGenerator<Instant> timesInRange(long startTime, long endDate) 118 { 119 checkThat(startTime < endDate, "startDate must come before endDate"); 120 121 Instant start = Instant.ofEpochMilli(startTime); 122 Instant end = Instant.ofEpochMilli(endDate); 123 124 return TimeGenerators.timesBetween(start, end); 125 } 126 } 127 128}