/* * Copyright (C) 2012 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */ package com.facebook.swift.codec.metadata; import com.facebook.swift.codec.BonkBean; import com.facebook.swift.codec.BonkBuilder; import com.facebook.swift.codec.BonkConstructor; import com.facebook.swift.codec.BonkField; import com.facebook.swift.codec.BonkMethod; import com.facebook.swift.codec.idlannotations.BeanWIthConflictingIdlAnnotationMapsForField; import com.facebook.swift.codec.idlannotations.BeanWithMatchingIdlAnnotationsMapsForField; import com.facebook.swift.codec.idlannotations.BeanWithOneIdlAnnotationMapForField; import com.facebook.swift.codec.idlannotations.ExceptionWithIdlAnnotations; import com.facebook.swift.codec.idlannotations.StructWithIdlAnnotations; import com.facebook.swift.codec.idlannotations.UnionWithIdlAnnotations; import com.facebook.swift.codec.metadata.ThriftStructMetadata.MetadataType; import org.testng.annotations.Test; import java.lang.reflect.Type; import java.util.Map; import static org.fest.assertions.Assertions.assertThat; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class TestThriftStructMetadata { @Test public void testField() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(BonkField.class, 0, 0); verifyFieldInjection(metadata, 1, "message"); verifyFieldExtraction(metadata, 1, "message"); verifyFieldInjection(metadata, 2, "type"); verifyFieldExtraction(metadata, 2, "type"); } private void verifyFieldInjection(ThriftStructMetadata metadata, int id, String name) { ThriftInjection injection = metadata.getField(id).getInjections().get(0); assertThat(injection).isNotNull().isInstanceOf(ThriftFieldInjection.class); ThriftFieldInjection fieldInjection = (ThriftFieldInjection) injection; assertEquals(fieldInjection.getField().getName(), name); } private void verifyFieldExtraction(ThriftStructMetadata metadata, int id, String name) { assertTrue(metadata.getField(id).getExtraction().isPresent()); ThriftExtraction extraction = metadata.getField(id).getExtraction().get(); assertThat(extraction).isInstanceOf(ThriftFieldExtractor.class); ThriftFieldExtractor fieldExtractor = (ThriftFieldExtractor) extraction; assertEquals(fieldExtractor.getField().getName(), name); } @Test public void testBean() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(BonkBean.class, 0, 2); verifyParameterInjection(metadata, 1, "message", 0); verifyMethodExtraction(metadata, 1, "message", "getMessage"); verifyParameterInjection(metadata, 2, "type", 0); verifyMethodExtraction(metadata, 2, "type", "getType"); } private void verifyParameterInjection(ThriftStructMetadata metadata, int id, String name, int parameterIndex) { ThriftInjection injection = metadata.getField(id).getInjections().get(0); assertThat(injection).isNotNull().isInstanceOf(ThriftParameterInjection.class); ThriftParameterInjection parameterInjection = (ThriftParameterInjection) injection; assertEquals(parameterInjection.getId(), id); assertEquals(parameterInjection.getName(), name); assertEquals(parameterInjection.getParameterIndex(), parameterIndex); } private void verifyMethodExtraction(ThriftStructMetadata metadata, int id, String name, String methodName) { assertTrue(metadata.getField(id).getExtraction().isPresent()); ThriftExtraction extraction = metadata.getField(id).getExtraction().get(); assertThat(extraction).isInstanceOf(ThriftMethodExtractor.class); ThriftMethodExtractor methodExtractor = (ThriftMethodExtractor) extraction; assertEquals(methodExtractor.getMethod().getName(), methodName); assertEquals(methodExtractor.getName(), name); } @Test public void testConstructor() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(BonkConstructor.class, 2, 0); verifyParameterInjection(metadata, 1, "message", 0); verifyMethodExtraction(metadata, 1, "message", "getMessage"); verifyParameterInjection(metadata, 2, "type", 1); verifyMethodExtraction(metadata, 2, "type", "getType"); } @Test public void testMethod() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(BonkMethod.class, 0, 1); verifyParameterInjection(metadata, 1, "message", 0); verifyMethodExtraction(metadata, 1, "message", "getMessage"); verifyParameterInjection(metadata, 2, "type", 1); verifyMethodExtraction(metadata, 2, "type", "getType"); } @Test public void testBuilder() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(BonkBuilder.class, 0, 2); verifyParameterInjection(metadata, 1, "message", 0); verifyMethodExtraction(metadata, 1, "message", "getMessage"); verifyParameterInjection(metadata, 2, "type", 0); verifyMethodExtraction(metadata, 2, "type", "getType"); } @Test public void testFieldWithOneIdlAnnotationMap() throws Exception { /** * Single field with IDL annotation map on getter, but not on setter: should be okay */ ThriftStructMetadata metadata = testStructMetadataBuild(BeanWithOneIdlAnnotationMapForField.class, 0, 1); Map<String, String> idlAnnotations = metadata.getField(2).getIdlAnnotations(); assertEquals(idlAnnotations.size(), 2); assertEquals(idlAnnotations.get("testkey1"), "testvalue1"); assertEquals(idlAnnotations.get("testkey2"), "testvalue2"); } @Test public void testFieldWithMatchingIdlAnnotationMaps() throws Exception { /** * Single field with matching IDL annotation maps on setter vs getter: should be okay */ ThriftStructMetadata metadata = testStructMetadataBuild(BeanWithMatchingIdlAnnotationsMapsForField.class, 0, 1); Map<String, String> idlAnnotations = metadata.getField(2).getIdlAnnotations(); assertEquals(idlAnnotations.size(), 2); assertEquals(idlAnnotations.get("testkey1"), "testvalue1"); assertEquals(idlAnnotations.get("testkey2"), "testvalue2"); } @Test(expectedExceptions = MetadataErrorException.class) public void testFieldWithConflictingIdlAnnotationMap() throws Exception { /** * Single field with conflicting IDL annotation maps on setter vs getter: should fail */ testStructMetadataBuild(BeanWIthConflictingIdlAnnotationMapsForField.class, 0, 1); } @Test public void testStructWithIdlAnnotationsMap() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(StructWithIdlAnnotations.class, 0, 0); Map<String, String> idlAnnotations = metadata.getIdlAnnotations(); assertEquals(idlAnnotations.size(), 2); assertEquals(idlAnnotations.get("testkey1"), "testvalue1"); assertEquals(idlAnnotations.get("testkey2"), "testvalue2"); } @Test public void testUnionWithIdlAnnotationsMap() throws Exception { ThriftStructMetadata metadata = testUnionMetadataBuild(UnionWithIdlAnnotations.class, 0, 2); Map<String, String> idlAnnotations = metadata.getIdlAnnotations(); assertEquals(idlAnnotations.size(), 2); assertEquals(idlAnnotations.get("testkey1"), "testvalue1"); assertEquals(idlAnnotations.get("testkey2"), "testvalue2"); } @Test public void testExceptionWithIdlAnnotationsMap() throws Exception { ThriftStructMetadata metadata = testStructMetadataBuild(ExceptionWithIdlAnnotations.class, 2, 0); Map<String, String> idlAnnotations = metadata.getIdlAnnotations(); assertEquals(idlAnnotations.size(), 1); assertEquals(idlAnnotations.get("message"), "message"); } private ThriftStructMetadata testStructMetadataBuild( Class<?> structClass, int expectedConstructorParameters, int expectedMethodInjections) throws Exception { return testMetadataBuild( ThriftStructMetadataBuilder.class, structClass, expectedConstructorParameters, expectedMethodInjections); } private ThriftStructMetadata testUnionMetadataBuild( Class<?> structClass, int expectedConstructorParameters, int expectedMethodInjections) throws Exception { return testMetadataBuild( ThriftUnionMetadataBuilder.class, structClass, expectedConstructorParameters, expectedMethodInjections); } private <T extends AbstractThriftMetadataBuilder> ThriftStructMetadata testMetadataBuild( Class<T> metadataBuilderType, Class<?> structClass, int expectedConstructorParameters, int expectedMethodInjections) throws Exception { ThriftStructMetadata metadata = buildMetadata(structClass, metadataBuilderType); assertNotNull(metadata); assertTrue( MetadataType.UNION == metadata.getMetadataType() || MetadataType.STRUCT == metadata.getMetadataType()); verifyField(metadata, 1, "message"); verifyField(metadata, 2, "type"); ThriftConstructorInjection constructorInjection = metadata.getConstructorInjection().get(); assertNotNull(constructorInjection); assertEquals(constructorInjection.getParameters().size(), expectedConstructorParameters); assertEquals(metadata.getMethodInjections().size(), expectedMethodInjections); return metadata; } private <T extends AbstractThriftMetadataBuilder> ThriftStructMetadata buildMetadata( Class<?> structClass, Class<T> metadataBuilderType) throws Exception { ThriftCatalog catalog = new ThriftCatalog(); AbstractThriftMetadataBuilder builder = metadataBuilderType.getConstructor(ThriftCatalog.class, Type.class) .newInstance(catalog, structClass); assertNotNull(builder); assertNotNull(builder.getMetadataErrors()); builder.getMetadataErrors().throwIfHasErrors(); assertEquals(builder.getMetadataErrors().getWarnings().size(), 0); return builder.build(); } private <T> void verifyField(ThriftStructMetadata metadata, int id, String name) { ThriftFieldMetadata messageField = metadata.getField(id); assertNotNull(messageField, "field '" + name + "' is null"); assertEquals(messageField.getId(), id); assertEquals(messageField.getName(), name); assertFalse(messageField.isReadOnly()); assertFalse(messageField.isWriteOnly()); assertTrue(messageField.getExtraction().isPresent()); ThriftExtraction extraction = messageField.getExtraction().get(); assertEquals(extraction.getId(), id); assertEquals(extraction.getName(), name); assertNotNull(messageField.getInjections()); assertEquals(messageField.getInjections().size(), 1); ThriftInjection injection = messageField.getInjections().get(0); assertEquals(injection.getId(), id); assertEquals(injection.getName(), name); } }