/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.datatorrent.stram.webapp; import java.util.List; import java.util.Map; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; import org.junit.Assert; import org.junit.Test; import com.google.common.collect.Maps; import com.datatorrent.api.DefaultInputPort; import com.datatorrent.api.DefaultOutputPort; import com.datatorrent.api.Operator; import com.datatorrent.common.util.BaseOperator; public class TypeDiscoveryTest { private interface GenericInterface<T> { } private static class StringOutputPort extends DefaultOutputPort<String> { public StringOutputPort(Operator operator) { super(); } } private static class A<K> { } private static class B<T extends Number> extends A { } private static class GenericOutputPort extends DefaultOutputPort<B<Number>> { public GenericOutputPort(Operator operator) { super(); } } private static class GenericSubClassOutputPort extends GenericOutputPort { public GenericSubClassOutputPort(Operator operator) { super(operator); } } static class ParameterizedOperator<T0, T1 extends Map<String, ? extends T0>, T2 extends Number> extends BaseOperator implements GenericInterface<T1> { final InputPort<T1> inputT1 = new DefaultInputPort<T1>() { @Override public void process(T1 tuple) { } }; final OutputPort<T2> outportT2 = new DefaultOutputPort<>(); final OutputPort<Number> outportNumberParam = new DefaultOutputPort<>(); final StringOutputPort outportString = new StringOutputPort(this); final OutputPort<List<T0>> outportList = new DefaultOutputPort<>(); final GenericSubClassOutputPort outClassObject = new GenericSubClassOutputPort(this); } static class ExtendsParameterizedOperator extends ParameterizedOperator<Number, Map<String, Double>, Double> { } static class SpecializedOperator extends BaseOperator { final InputPort<String> inputT1 = new DefaultInputPort<String>() { @Override public void process(String tuple) { } }; final OutputPort<Map<String, Number>> outportT2 = new DefaultOutputPort<>(); final OutputPort<Number> outportNumberParam = new DefaultOutputPort<>(); final StringOutputPort outportString = new StringOutputPort(this); } public static class DiscoveryContext { JSONObject json = new JSONObject(); Map<String, String> resolvedTypeParams = Maps.newHashMap(); } @Test public void testTypeDiscovery() throws Exception { String[] classFilePath = OperatorDiscoveryTest.getClassFileInClasspath(); OperatorDiscoverer od = new OperatorDiscoverer(classFilePath); od.buildTypeGraph(); JSONObject Desc = od.describeClassByASM(ExtendsParameterizedOperator.class.getName()); JSONArray json = Desc.getJSONArray("portTypeInfo"); String debug = "\n(ASM)type info for " + ExtendsParameterizedOperator.class + ":\n" + Desc.toString(2) + "\n"; ObjectMapper mapper = new ObjectMapper(); //List<?> l = mapper.convertValue(json, List.class); JsonNode root = mapper.readTree(json.toString(2)); String val = root.get(0).path("name").asText(); Assert.assertEquals(debug + "port name", "inputT1", val); val = root.get(3).path("name").asText(); Assert.assertEquals(debug + "port name", "outportString", val); val = root.get(3).path("type").asText(); Assert.assertEquals(debug + "outportList type", "java.lang.String", val); val = root.get(4).path("name").asText(); Assert.assertEquals(debug + "port name", "outportList", val); val = root.get(4).path("type").asText(); Assert.assertEquals(debug + "outportList type", "java.util.List", val); val = root.get(4).path("typeArgs").get(0).path("type").asText(); Assert.assertEquals(debug + "outportList type", "java.lang.Number", val); val = root.get(5).path("name").asText(); Assert.assertEquals(debug + "port name", "outClassObject", val); val = root.get(5).path("type").asText(); Assert.assertEquals(debug + "outportList type", "com.datatorrent.stram.webapp.TypeDiscoveryTest$B", val); val = root.get(5).path("typeArgs").get(0).path("type").asText(); Assert.assertEquals(debug + "outportList type", "java.lang.Number", val); } static class ParameterizedTypeOperator<T> extends BaseOperator { final OutputPort<T> output = new DefaultOutputPort<>(); } static class StringParameterOperator extends ParameterizedTypeOperator<String> { } @Test public void testTypeDiscovery2() throws Exception { String[] classFilePath = OperatorDiscoveryTest.getClassFileInClasspath(); OperatorDiscoverer od = new OperatorDiscoverer(classFilePath); od.buildTypeGraph(); JSONObject Desc = od.describeClassByASM(StringParameterOperator.class.getName()); JSONArray json = Desc.getJSONArray("portTypeInfo"); String debug = "\n(ASM)type info for " + StringParameterOperator.class + ":\n" + Desc.toString(2) + "\n"; ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json.toString(2)); String val = root.get(0).path("name").asText(); Assert.assertEquals(debug + "port name", "output", val); val = root.get(0).path("type").asText(); Assert.assertEquals(debug + "port type", "java.lang.String", val); } static class SubClass<K> extends ParameterizedTypeOperator<K> { } static class SubSubClass extends SubClass<Map<String, Object>> { public String trial; } @Test public void testTypeDiscoveryMultiLevel() throws Exception { String[] classFilePath = OperatorDiscoveryTest.getClassFileInClasspath(); OperatorDiscoverer od = new OperatorDiscoverer(classFilePath); od.buildTypeGraph(); JSONObject Desc = od.describeClassByASM(SubSubClass.class.getName()); JSONArray json = Desc.getJSONArray("portTypeInfo"); String debug = "\n(ASM)type info for " + SubSubClass.class + ":\n" + Desc.toString(2) + "\n"; ObjectMapper mapper = new ObjectMapper(); JsonNode root = mapper.readTree(json.toString(2)); String val = root.get(0).path("name").asText(); Assert.assertEquals(debug + "port name", "output", val); val = root.get(0).path("type").asText(); Assert.assertEquals(debug + "port type", "java.util.Map", val); val = root.get(0).path("typeArgs").get(0).path("type").asText(); Assert.assertEquals(debug + "map key type", "java.lang.String", val); val = root.get(0).path("typeArgs").get(1).path("type").asText(); Assert.assertEquals(debug + "map value type", "java.lang.Object", val); } @Test public void testAppAttributes() throws JSONException, IllegalAccessException { JSONArray appAttributes = TypeDiscoverer.getAppAttributes().getJSONArray("attributes"); Map<String, JSONObject> attributesMap = Maps.newHashMap(); for (int i = 0; i < appAttributes.length(); i++) { attributesMap.put(appAttributes.getJSONObject(i).getString("name"), appAttributes.getJSONObject(i)); } JSONObject appNameAttr = attributesMap.get("APPLICATION_NAME"); Assert.assertNotNull("application name", appNameAttr); Assert.assertEquals("application name type", "java.lang.String", appNameAttr.getString("type")); Assert.assertNotNull("default app name", appNameAttr.getString("default")); JSONObject stringCodecsAttr = attributesMap.get("STRING_CODECS"); Assert.assertNotNull("string codecs", stringCodecsAttr); Assert.assertEquals("string codecs type", "java.util.Map", stringCodecsAttr.getString("type")); Assert.assertNotNull("type args", stringCodecsAttr.getJSONArray("typeArgs")); } @Test public void testOperatorAttributes() throws JSONException, IllegalAccessException { JSONArray operatorAttributes = TypeDiscoverer.getOperatorAttributes().getJSONArray("attributes"); Map<String, JSONObject> attributesMap = Maps.newHashMap(); for (int i = 0; i < operatorAttributes.length(); i++) { attributesMap.put(operatorAttributes.getJSONObject(i).getString("name"), operatorAttributes.getJSONObject(i)); } JSONObject activationWindowAttr = attributesMap.get("ACTIVATION_WINDOW_ID"); Assert.assertNotNull("activation window", activationWindowAttr); Assert.assertEquals("activation window type", "java.lang.Long", activationWindowAttr.getString("type")); Assert.assertEquals("default activation window", "-1", activationWindowAttr.getString("default")); JSONObject partitionerAttr = attributesMap.get("PARTITIONER"); Assert.assertNotNull("partitioner", partitionerAttr); Assert.assertEquals("partitioner type", "com.datatorrent.api.Partitioner", partitionerAttr.getString("type")); Assert.assertNotNull("type args", partitionerAttr.getJSONArray("typeArgs")); JSONObject processingModeAttr = attributesMap.get("PROCESSING_MODE"); Assert.assertNotNull("processingModeAttr", processingModeAttr); Assert.assertEquals("processing mode type", "com.datatorrent.api.Operator$ProcessingMode", processingModeAttr.getString("type")); Assert.assertEquals("ui type", "Enum", processingModeAttr.getString("uiType")); } @Test public void testPortAttributes() throws JSONException, IllegalAccessException { JSONArray portAttributes = TypeDiscoverer.getPortAttributes().getJSONArray("attributes"); Map<String, JSONObject> attributesMap = Maps.newHashMap(); for (int i = 0; i < portAttributes.length(); i++) { attributesMap.put(portAttributes.getJSONObject(i).getString("name"), portAttributes.getJSONObject(i)); } JSONObject queueCapacityAttr = attributesMap.get("QUEUE_CAPACITY"); Assert.assertNotNull("queue capacity", queueCapacityAttr); Assert.assertEquals("queue capacity type", "java.lang.Integer", queueCapacityAttr.getString("type")); Assert.assertEquals("default queue capacity", "1024", queueCapacityAttr.getString("default")); JSONObject streamCodecAttr = attributesMap.get("STREAM_CODEC"); Assert.assertNotNull("stream codec", streamCodecAttr); Assert.assertEquals("stream codec type", "com.datatorrent.api.StreamCodec", streamCodecAttr.getString("type")); Assert.assertNotNull("type args", streamCodecAttr.getJSONArray("typeArgs")); } }