package io.swagger.models.properties; import io.swagger.models.ArrayModel; import io.swagger.models.Model; import io.swagger.models.ModelImpl; import io.swagger.models.properties.PropertyBuilder.PropertyId; import io.swagger.models.properties.StringProperty.Format; import org.mockito.Matchers; import org.mockito.Mockito; import org.testng.annotations.BeforeMethod; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.EnumMap; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; import static org.testng.Assert.assertTrue; public class PropertyBuilderTest { private static final String STRING_FORMATS = "stringFormats"; private static final String FROM_SPEC = "fromSpec"; private static final String BY_IMPLEMENTATION = "predefined"; private static final String CUSTOM_OR_PLAIN = "customOrPlain"; private HashMap<PropertyId, Object> args; private List<String> _enum; @DataProvider(name = BY_IMPLEMENTATION) public Iterator<Object[]> createPredefinedProperties() { Property[] properties = {new DecimalProperty(), new FloatProperty(), new DoubleProperty(), new BaseIntegerProperty(), new IntegerProperty(), new LongProperty(), new StringProperty(), new UUIDProperty(), new BooleanProperty(), new ByteArrayProperty(), new ArrayProperty(), new ObjectProperty(), new DateTimeProperty(), new DateProperty(), new RefProperty(), new EmailProperty(), // new MapProperty() // MapProperty can't be distinguished from // ObjectProperty }; List<Object[]> resultList = new ArrayList<Object[]>(properties.length); for (Property property : properties) { resultList.add(new Object[]{property.getType(), property.getFormat(), property.getClass()}); } return resultList.iterator(); } @DataProvider(name = STRING_FORMATS) public Iterator<Object[]> createPredefinedStringFormats() { List<Object[]> resultList = new ArrayList<Object[]>(); for (Format format : StringProperty.Format.values()) { resultList.add(new Object[]{StringProperty.TYPE, format.getName(), StringProperty.class}); } return resultList.iterator(); } @DataProvider(name = FROM_SPEC) public Object[][] createDataFromSpec() { // from the table in http://swagger.io/specification/#dataTypeType return new Object[][] { {"integer", "int32", IntegerProperty.class}, {"integer", "int64", LongProperty.class}, {"number", "float", FloatProperty.class}, {"number", "double", DoubleProperty.class}, {"string", null, StringProperty.class}, {"string", "byte", ByteArrayProperty.class}, {"string", "binary", BinaryProperty.class}, {"boolean", null, BooleanProperty.class}, {"string", "date", DateProperty.class}, {"string", "date-time", DateTimeProperty.class}, {"string", "password", StringProperty.class}, }; } @DataProvider(name = CUSTOM_OR_PLAIN) public Object[][] createCustomAndPlainData() { // these are the types without formats (as long as not already in the // table in the spec), and a "custom" format for each of the types. // we expect to get the same Property class back in both cases. return new Object[][]{{"integer", null, BaseIntegerProperty.class}, {"integer", "custom", BaseIntegerProperty.class}, {"number", null, DecimalProperty.class}, {"number", "custom", DecimalProperty.class}, {"string", "custom", StringProperty.class}, {"boolean", "custom", BooleanProperty.class}, {"object", null, ObjectProperty.class}, {"object", "custom", ObjectProperty.class}, {"array", null, ArrayProperty.class}, {"array", "custom", ArrayProperty.class}}; } @Test(dataProvider = BY_IMPLEMENTATION) public void testPredefinedProperty(final String type, final String format, final Class<? extends Property> expectedClass) { buildAndAssertProperty(type, format, expectedClass); } @Test(dataProvider = FROM_SPEC) public void testSpecificationProperty(final String type, final String format, final Class<? extends Property> expectedClass) { buildAndAssertProperty(type, format, expectedClass); } @Test(dataProvider = CUSTOM_OR_PLAIN) public void testCustomOrPlainProperty(final String type, final String format, final Class<? extends Property> expectedClass) { buildAndAssertProperty(type, format, expectedClass); } @Test(dataProvider = STRING_FORMATS) public void testStringPredefinedFormats(final String type, final String format, final Class<? extends Property> expectedClass) { buildAndAssertProperty(type, format, expectedClass); } private void buildAndAssertProperty(final String type, final String format, final Class<? extends Property> expectedClass) { Property built = PropertyBuilder.build(type, format, null); assertNotNull(built, "Could not build for type: " + type + ", format: " + format + ", expected class: " + expectedClass); assertEquals(built.getClass(), expectedClass); assertEquals(built.getType(), type); assertEquals(built.getFormat(), format); } @Test public void testUnknownType() { assertNull(PropertyBuilder.build("unknownType", "custom", null)); } @Test(dataProvider = FROM_SPEC) public void testBuildWithArgs(final String type, final String format, final Class<? extends Property> expectedClass) { EnumMap<PropertyId, Object> args = new EnumMap<PropertyId, Object>(PropertyId.class); args.put(PropertyId.DESCRIPTION, "Example description"); args.put(PropertyId.MIN_LENGTH, 2); args.put(PropertyId.MAX_LENGTH, 11); args.put(PropertyId.PATTERN, "pattern"); Property built = PropertyBuilder.build(type, format, args); assertNotNull(built); assertEquals(built.getClass(), expectedClass); } @BeforeMethod public void setup() { args = new HashMap<PropertyBuilder.PropertyId, Object>(); args.put(PropertyId.READ_ONLY, true); String title = "title"; args.put(PropertyId.TITLE, title); String description = "description"; args.put(PropertyId.DESCRIPTION, description); String example = "example"; args.put(PropertyId.EXAMPLE, example); Map<String, Object> vendorExtensions = new HashMap<String, Object>(); args.put(PropertyId.VENDOR_EXTENSIONS, vendorExtensions); _enum = Arrays.asList("4", "hello"); args.put(PropertyId.ENUM, _enum); args.put(PropertyId.DEFAULT, "4"); } @Test public void testMergeWithIntegerProperty() { // given IntegerProperty integerProperty = new IntegerProperty(); // when PropertyBuilder.merge(integerProperty, args); // then assertTrue(integerProperty.getEnum().contains(4), "Must contain the enum value passed into args"); assertEquals(integerProperty.getDefault(), (Integer) 4, "Must contain the default value passed into args"); // given args.put(PropertyId.DEFAULT, null); // when PropertyBuilder.merge(integerProperty, args); // then assertNull(integerProperty.getDefault(), "Must contain the default value passed into args"); } @Test public void testMergeWithBooleanProperty() { // given args.put(PropertyId.DEFAULT, "true"); BooleanProperty booleanProperty = new BooleanProperty(); // when PropertyBuilder.merge(booleanProperty, args); // then assertEquals(booleanProperty.getDefault(), Boolean.TRUE, "Must contain the default value passed into args"); // given args.put(PropertyId.DEFAULT, null); // when PropertyBuilder.merge(booleanProperty, args); // then assertNull(booleanProperty.getDefault(), "Must contain the default value passed into args"); } @Test public void testMergeWithLongProperty() { // given args.put(PropertyId.DEFAULT, "4"); LongProperty longProperty = new LongProperty(); // when PropertyBuilder.merge(longProperty, args); // then assertTrue(longProperty.getEnum().contains(4L), "Must contain the enum value passed into args"); assertEquals(longProperty.getDefault(), (Object) 4L, "Must contain the default value passed into args"); // given args.put(PropertyId.DEFAULT, null); // when PropertyBuilder.merge(longProperty, args); // then assertNull(longProperty.getDefault(), "Must contain the default value passed into args"); } @Test public void testMergeWithFloatProperty() { // given args.put(PropertyId.DEFAULT, "4"); FloatProperty floatProperty = new FloatProperty(); // when PropertyBuilder.merge(floatProperty, args); // then assertTrue(floatProperty.getEnum().contains(4F), "Must contain the enum value passed into args"); assertEquals(floatProperty.getDefault(), new BigDecimal(4).floatValue(), "Must contain the default value passed into args"); // given args.put(PropertyId.DEFAULT, null); // when PropertyBuilder.merge(floatProperty, args); // then assertNull(floatProperty.getDefault(), "Must contain the default value passed into args"); } @Test public void testMergeWithUUIDProperty() { // given UUIDProperty uuidProperty = new UUIDProperty(); args.put(PropertyId.DEFAULT, "default"); args.put(PropertyId.MIN_LENGTH, 2); args.put(PropertyId.MAX_LENGTH, 11); args.put(PropertyId.PATTERN, "pattern"); // when PropertyBuilder.merge(uuidProperty, args); // then assertEquals(uuidProperty.getDefault(), "default", "Must contain the default value passed into args"); assertEquals(uuidProperty.getMinLength(), (Object) 2, "Must contain the minLength value passed into args"); assertEquals(uuidProperty.getMaxLength(), (Object) 11, "Must contain the maxLength value passed into args"); assertEquals(uuidProperty.getPattern(), "pattern", "Must contain the pattern value passed into args"); // given uuidProperty = Mockito.spy(uuidProperty); Mockito.doThrow(new RuntimeException()).when(uuidProperty)._enum(Matchers.anyString()); // when PropertyBuilder.merge(uuidProperty, args); // then assertEquals(uuidProperty.getEnum(), _enum, "Must contain the enum value passed into args"); } @Test public void testMergeWithArrayProperty() { // given ArrayProperty arrayProperty = new ArrayProperty(); args.put(PropertyId.MIN_ITEMS, 2); args.put(PropertyId.MAX_ITEMS, 11); // when PropertyBuilder.merge(arrayProperty, args); // then assertEquals(arrayProperty.getMinItems(), (Object) 2, "Must contain the minItems value passed into args"); assertEquals(arrayProperty.getMaxItems(), (Object) 11, "Must contain the maxItems value passed into args"); } @Test public void testMergeWithDateProperty() { // given DateProperty dateProperty = new DateProperty(); // when PropertyBuilder.merge(dateProperty, args); // then assertEquals(dateProperty.getEnum(), _enum, "Must contain the enum value passed into args"); // given dateProperty = Mockito.spy(dateProperty); Mockito.doThrow(new RuntimeException()).when(dateProperty)._enum(Matchers.anyString()); // when PropertyBuilder.merge(dateProperty, args); // then assertEquals(dateProperty.getEnum(), _enum, "Must contain the enum value passed into args"); } @Test public void testMergeWithDateTimeProperty() { // given DateTimeProperty dateTimeProperty = new DateTimeProperty(); // when PropertyBuilder.merge(dateTimeProperty, args); // then assertEquals(dateTimeProperty.getEnum(), _enum, "Must contain the enum value passed into args"); // given dateTimeProperty = Mockito.spy(dateTimeProperty); Mockito.doThrow(new RuntimeException()).when(dateTimeProperty)._enum(Matchers.anyString()); // when PropertyBuilder.merge(dateTimeProperty, args); // then assertEquals(dateTimeProperty.getEnum(), _enum, "Must contain the enum value passed into args"); } @Test public void testMergeWithStringProperty() { // given StringProperty stringProperty = new StringProperty(); // when PropertyBuilder.merge(stringProperty, args); // then assertEquals(stringProperty.getEnum(), _enum, "Must contain the enum value passed into args"); } @Test public void testMergeWithDoubleProperty() { // given args.put(PropertyId.MINIMUM, new BigDecimal(2.0)); args.put(PropertyId.MAXIMUM, new BigDecimal(112.0)); args.put(PropertyId.EXCLUSIVE_MINIMUM, true); args.put(PropertyId.EXCLUSIVE_MAXIMUM, true); args.put(PropertyId.MULTIPLE_OF, new BigDecimal(2.0)); args.put(PropertyId.DEFAULT, "4"); DoubleProperty doubleProperty = new DoubleProperty(); // when PropertyBuilder.merge(doubleProperty, args); // then assertTrue(doubleProperty.getEnum().contains(4.0), "Must contain the enum value passed into args"); assertEquals(doubleProperty.getDefault(), (Double) 4.0, "Must contain the default value passed into args"); assertEquals(doubleProperty.getMinimum(), new BigDecimal(2.0), "Must contain the minimum value passed into args"); assertEquals(doubleProperty.getMaximum(), new BigDecimal(112.0), "Must contain the maximum value passed into args"); assertTrue(doubleProperty.exclusiveMaximum, "Must contain the exclusive minimum value passed into args"); assertTrue(doubleProperty.exclusiveMinimum, "Must contain the exclusive maximum value passed into args"); assertEquals(doubleProperty.getMultipleOf(), new BigDecimal(2.0), "Must contain the multiple of value passed into args"); // given args.put(PropertyId.DEFAULT, null); // when PropertyBuilder.merge(doubleProperty, args); // then assertNull(doubleProperty.getDefault(), "Must contain the default value passed into args"); } @Test public void testToModelWithBooleanProperty() { // given BooleanProperty booleanProperty = new BooleanProperty(); booleanProperty.setDescription("description"); // when Model model = PropertyBuilder.toModel(booleanProperty); // then assertEquals(model.getDescription(), booleanProperty.getDescription(), "Must contain the description value passed into the property"); } @Test public void testToModelWithIntegerProperty() { // given IntegerProperty integerProperty = new IntegerProperty(); integerProperty.setDefault(4); Model model = PropertyBuilder.toModel(integerProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), 4, "Must contain the default value passed into the property"); } @Test public void testToModelWithLongProperty() { // given LongProperty longProperty = new LongProperty(); longProperty.setDefault(4L); // when Model model = PropertyBuilder.toModel(longProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), 4, "Must contain the default value passed into the property"); } @Test public void testToModelWithFloatProperty() { // given FloatProperty floatProperty = new FloatProperty(); floatProperty.setDefault(4F); // when Model model = PropertyBuilder.toModel(floatProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), new BigDecimal("4.0"), "Must contain the default value passed into the property"); } @Test public void testToModelWithDoubleProperty() { // given DoubleProperty doubleProperty = new DoubleProperty(); doubleProperty.setDefault(4D); // when Model model = PropertyBuilder.toModel(doubleProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), new BigDecimal("4.0"), "Must contain the default value passed into the property"); } @Test public void testToModelWithRefProperty() { // given RefProperty refProperty = new RefProperty("ref"); // when refProperty.setDescription("ref description"); // then assertEquals(PropertyBuilder.toModel(refProperty).getDescription(), refProperty.getDescription(), "Must contain the description value passed into the property"); } @Test public void testToModelWithEmailProperty() { // given EmailProperty emailProperty = new EmailProperty(); emailProperty.setDefault("default"); // when Model model = PropertyBuilder.toModel(emailProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), "default", "Must contain the default value passed into the property"); } @Test public void testToModelWithArrayProperty() { // given EmailProperty emailProperty = new EmailProperty(); ArrayProperty arrayProperty = new ArrayProperty(); arrayProperty.setItems(emailProperty); // when Model model = PropertyBuilder.toModel(arrayProperty); // then assertEquals(((ArrayModel) model).getItems(), emailProperty, "Must contain the items value passed into the property"); } @Test public void testToModelWithMapProperty() { // given EmailProperty emailProperty = new EmailProperty(); MapProperty mapProperty = new MapProperty(); mapProperty.setAdditionalProperties(emailProperty); // when Model model = PropertyBuilder.toModel(mapProperty); // then assertEquals(((ModelImpl) model).getAdditionalProperties(), emailProperty, "Must contain the additionalProperties value passed into the property"); } @Test public void testToModelWithStringProperty() { // given StringProperty stingProperty = new StringProperty(); stingProperty.setDefault("default"); // when Model model = PropertyBuilder.toModel(stingProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), "default", "Must contain the default value passed into the property"); } @Test public void testToModelWithUUIDProperty() { // given UUIDProperty uuidProperty = new UUIDProperty(); uuidProperty.setDefault("default"); // when Model model = PropertyBuilder.toModel(uuidProperty); // then assertEquals(((ModelImpl) model).getDefaultValue(), "default", "Must contain the default value passed into the property"); } @Test public void testToModelWithUnknownPropertyType() { assertNull(PropertyBuilder.toModel(Mockito.mock(Property.class))); } @Test public void testGetPropertyName() { // when String name = PropertyId.DEFAULT.getPropertyName(); // then assertEquals(name, "default", "Property name for DEFAULT is 'default'"); } @Test public void testValueOf() { // when PropertyId value = PropertyId.valueOf("DEFAULT"); // then assertEquals(value, PropertyId.DEFAULT, "Value of 'DEFAULT' is DEFAULT"); } }