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.nio.ByteBuffer; 022import java.time.Instant; 023import java.util.Date; 024import java.util.List; 025import tech.sirwellington.alchemy.annotations.access.Internal; 026import tech.sirwellington.alchemy.annotations.access.NonInstantiable; 027import tech.sirwellington.alchemy.generator.AlchemyGenerator; 028import tech.sirwellington.alchemy.generator.BinaryGenerators; 029import tech.sirwellington.alchemy.generator.BooleanGenerators; 030import tech.sirwellington.alchemy.generator.CollectionGenerators; 031import tech.sirwellington.alchemy.generator.DateGenerators; 032import tech.sirwellington.alchemy.generator.NumberGenerators; 033import tech.sirwellington.alchemy.generator.TimeGenerators; 034 035import static java.lang.annotation.ElementType.FIELD; 036import static java.lang.annotation.RetentionPolicy.RUNTIME; 037import static tech.sirwellington.alchemy.generator.CollectionGenerators.listOf; 038import static tech.sirwellington.alchemy.generator.NumberGenerators.positiveIntegers; 039import static tech.sirwellington.alchemy.generator.NumberGenerators.positiveLongs; 040import static tech.sirwellington.alchemy.generator.ObjectGenerators.pojos; 041import static tech.sirwellington.alchemy.generator.StringGenerators.alphanumericString; 042import static tech.sirwellington.alchemy.test.Checks.Internal.checkNotNull; 043import static tech.sirwellington.alchemy.test.Checks.Internal.checkThat; 044 045/** 046 * Used in with the {@link AlchemyTestRunner}, this Annotations allows the Runtime Injection of {@link List} values, using 047 * {@link CollectionGenerators} from the {@link AlchemyGenerator} library. 048 * 049 * Example: 050 * <pre> 051 * {@code 052 * `@RunWith(AlchemyTestRunner.class) 053 * public class ExampleTest 054 * { 055 * 056 * `@GenerateList(String.class) 057 * private List<String> ids; 058 * 059 * ... 060 * } 061 * } 062 * </pre> Note, ticks (`) used to escape Javadocs. 063 * 064 * @see GenerateEnum 065 * @see GeneratePojo 066 * 067 * @author SirWellington 068 */ 069@Target(FIELD) 070@Retention(RUNTIME) 071public @interface GenerateList 072{ 073 074 /** 075 * Specify the Generic Type of the List. This is necessary since the type information is erased at Runtime. 076 * 077 * @return 078 */ 079 Class<?> value(); 080 081 /** 082 * The number of elements to include in the list. Defaults to 10. This number must be {@code > 0}. 083 * 084 * @return 085 */ 086 int size() default 10; 087 088 @Internal 089 @NonInstantiable 090 static class Values 091 { 092 093 private Values() throws IllegalAccessException 094 { 095 throw new IllegalAccessException("cannot instantiate"); 096 } 097 098 static AlchemyGenerator<List<?>> createGeneratorFor(GenerateList annotation) throws IllegalArgumentException 099 { 100 checkNotNull(annotation, "missing annotation"); 101 int size = annotation.size(); 102 checkThat(size > 0, "size must be > 0"); 103 104 Class<?> genericType = annotation.value(); 105 checkNotNull(genericType, "annotation is missing generic type information"); 106 107 AlchemyGenerator<?> generator = determineGeneratorFor(genericType); 108 109 return () -> listOf(generator, size); 110 } 111 112 private static AlchemyGenerator<?> determineGeneratorFor(Class<?> genericType) 113 { 114 if (genericType == String.class) 115 { 116 return alphanumericString(); 117 } 118 119 if (genericType == Integer.class) 120 { 121 return positiveIntegers(); 122 } 123 124 if (genericType == Long.class) 125 { 126 return positiveLongs(); 127 } 128 129 if (genericType == Double.class) 130 { 131 return NumberGenerators.doubles(0, 10000); 132 } 133 134 if (Date.class.isAssignableFrom(genericType)) 135 { 136 return DateGenerators.anyTime(); 137 } 138 139 if (genericType == Instant.class) 140 { 141 return TimeGenerators.anytime(); 142 } 143 144 if (genericType == Boolean.class) 145 { 146 return BooleanGenerators.booleans(); 147 } 148 149 if (ByteBuffer.class.isAssignableFrom(genericType)) 150 { 151 return BinaryGenerators.byteBuffers(1024); 152 } 153 154 return pojos(genericType); 155 } 156 } 157 158}