ThriftStructProcessorTest.java
/*
* 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 org.apache.thrift.partial;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.thrift.TBase;
import org.apache.thrift.TException;
import org.apache.thrift.TFieldIdEnum;
import org.junit.jupiter.api.Test;
public class ThriftStructProcessorTest {
private PartialThriftTestData testData = new PartialThriftTestData();
@Test
public void testStruct() throws TException {
List<ThriftField> fields = ThriftField.fromNames(Collections.singletonList("i32Field"));
ThriftMetadata.ThriftStruct metadata =
ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, fields);
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.createNewStruct(metadata);
assertNotNull(instance);
assertTrue(instance instanceof TBase);
assertTrue(instance instanceof TestStruct);
Object instance2 = processor.prepareStruct(instance);
assertSame(instance, instance2);
}
@Test
public void testList() throws TException {
final int numItems = 10;
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.createNewList(numItems);
assertNotNull(instance);
assertTrue(instance instanceof Object[]);
Object[] items = (Object[]) instance;
for (int i = 0; i < numItems; i++) {
assertNull(items[i]);
processor.setListElement(instance, i, Integer.valueOf(i));
assertEquals(i, items[i]);
}
assertTrue(processor.prepareList(instance) instanceof List<?>);
}
@Test
public void testMap() throws TException {
final int numItems = 10;
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.createNewMap(numItems);
assertNotNull(instance);
assertTrue(instance instanceof Map<?, ?>);
Map<Object, Object> items = (Map<Object, Object>) instance;
int ignoredIndex = -1;
for (int i = 0; i < numItems; i++) {
assertNull(items.get(i));
processor.setMapElement(instance, ignoredIndex, Integer.valueOf(i), Integer.valueOf(i));
assertEquals(i, items.get(i));
}
assertTrue(processor.prepareMap(instance) instanceof Map<?, ?>);
}
@Test
public void testSet() throws TException {
final int numItems = 10;
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.createNewSet(numItems);
assertNotNull(instance);
assertTrue(instance instanceof HashSet<?>);
Set<?> items = (HashSet<?>) instance;
int ignoredIndex = -1;
for (int i = 0; i < numItems; i++) {
assertFalse(items.contains(i));
processor.setSetElement(instance, ignoredIndex, Integer.valueOf(i));
assertTrue(items.contains(i));
}
assertTrue(processor.prepareSet(instance) instanceof Set<?>);
}
@Test
public void testPrepareEnum() throws TException {
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.prepareEnum(TstEnum.class, 1);
assertNotNull(instance);
assertEquals(TstEnum.E_ONE, instance);
instance = processor.prepareEnum(TstEnum.class, 2);
assertNotNull(instance);
assertEquals(TstEnum.E_TWO, instance);
}
@Test
public void testPrepareString() throws TException {
ThriftStructProcessor processor = new ThriftStructProcessor();
ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]);
Object instance = processor.prepareString(emptyBuffer);
assertNotNull(instance);
assertTrue(instance instanceof String);
assertEquals("", instance);
String value = "Hello world!";
ByteBuffer buffer = ByteBuffer.wrap(value.getBytes(StandardCharsets.UTF_8));
instance = processor.prepareString(buffer);
assertNotNull(instance);
assertTrue(instance instanceof String);
assertEquals(value, instance);
}
@Test
public void testPrepareBinary() throws TException {
ThriftStructProcessor processor = new ThriftStructProcessor();
ByteBuffer emptyBuffer = ByteBuffer.wrap(new byte[0]);
Object instance = processor.prepareBinary(emptyBuffer);
assertNotNull(instance);
assertTrue(instance instanceof ByteBuffer);
assertSame(emptyBuffer, instance);
}
@Test
public void testStructPrimitiveFields() throws TException {
List<ThriftField> fields =
ThriftField.fromNames(
Arrays.asList(
"byteField",
"i16Field",
"i32Field",
"i64Field",
"doubleField",
"stringField",
"enumField",
"binaryField"));
ThriftMetadata.ThriftStruct metadata =
ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, fields);
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.createNewStruct(metadata);
assertNotNull(instance);
assertTrue(instance instanceof TBase);
assertTrue(instance instanceof TestStruct);
TestStruct struct = (TestStruct) instance;
// byte
TFieldIdEnum fieldId = findFieldId(metadata, "byteField");
assertNull(getFieldValue(struct, fieldId));
processor.setByte(struct, fieldId, (byte) 42);
assertEquals(42, struct.getByteField());
// short
fieldId = findFieldId(metadata, "i16Field");
assertNull(getFieldValue(struct, fieldId));
processor.setInt16(struct, fieldId, (short) 42);
assertEquals(42, struct.getI16Field());
// int
fieldId = findFieldId(metadata, "i32Field");
assertNull(getFieldValue(struct, fieldId));
processor.setInt32(struct, fieldId, 42);
assertEquals(42, struct.getI32Field());
// long
fieldId = findFieldId(metadata, "i64Field");
assertNull(getFieldValue(struct, fieldId));
processor.setInt64(struct, fieldId, 42L);
assertEquals(42, struct.getI64Field());
// binary
fieldId = findFieldId(metadata, "binaryField");
assertNull(getFieldValue(struct, fieldId));
byte[] noBytes = new byte[0];
ByteBuffer emptyBuffer = ByteBuffer.wrap(noBytes);
processor.setBinary(struct, fieldId, emptyBuffer);
assertArrayEquals(noBytes, struct.getBinaryField());
// string
fieldId = findFieldId(metadata, "stringField");
assertNull(getFieldValue(struct, fieldId));
String value = "Hello world!";
ByteBuffer buffer = ByteBuffer.wrap(value.getBytes(StandardCharsets.UTF_8));
processor.setString(struct, fieldId, buffer);
assertEquals(value, struct.getStringField());
// enum
fieldId = findFieldId(metadata, "enumField");
assertNull(getFieldValue(struct, fieldId));
TstEnum e1 = TstEnum.E_ONE;
processor.setEnumField(struct, fieldId, e1);
assertEquals(TstEnum.E_ONE, struct.getEnumField());
}
@Test
public void testStructContainerFields() throws TException {
List<ThriftField> fields =
ThriftField.fromNames(
Arrays.asList(
// List field
"i32List",
// Set field
"stringSet",
// Map field
"stringMap",
// Struct field
"structField"));
ThriftMetadata.ThriftStruct metadata =
ThriftMetadata.ThriftStruct.fromFields(TestStruct.class, fields);
ThriftStructProcessor processor = new ThriftStructProcessor();
Object instance = processor.createNewStruct(metadata);
assertNotNull(instance);
assertTrue(instance instanceof TBase);
assertTrue(instance instanceof TestStruct);
TestStruct struct = (TestStruct) instance;
// list
TFieldIdEnum fieldId = findFieldId(metadata, "i32List");
assertNull(getFieldValue(struct, fieldId));
Integer[] ints = new Integer[] {1, 2, 3};
List<Integer> intList = Arrays.asList(ints);
processor.setListField(struct, fieldId, intList);
assertArrayEquals(ints, struct.getI32List().toArray());
// set
fieldId = findFieldId(metadata, "stringSet");
assertNull(getFieldValue(struct, fieldId));
String[] strings = new String[] {"Hello", "World!"};
Set<String> stringSet = new HashSet<>(Arrays.asList(strings));
processor.setSetField(struct, fieldId, stringSet);
assertEquals(stringSet, struct.getStringSet());
// map
fieldId = findFieldId(metadata, "stringMap");
assertNull(getFieldValue(struct, fieldId));
Map<String, String> stringMap = new HashMap<>();
stringMap.put("foo", "bar");
stringMap.put("Hello", "World!");
processor.setMapField(struct, fieldId, stringMap);
assertEquals(stringMap, struct.getStringMap());
// struct
fieldId = findFieldId(metadata, "structField");
assertNull(getFieldValue(struct, fieldId));
SmallStruct smallStruct = new SmallStruct();
smallStruct.setI32Field(42);
SmallStruct smallStruct2 = new SmallStruct();
smallStruct2.setI32Field(42);
processor.setStructField(struct, fieldId, smallStruct);
assertEquals(smallStruct2, struct.getStructField());
}
private TFieldIdEnum findFieldId(ThriftMetadata.ThriftStruct metadata, String fieldName) {
Collection<ThriftMetadata.ThriftObject> fields = metadata.fields.values();
for (ThriftMetadata.ThriftObject field : fields) {
if (fieldName.equalsIgnoreCase(field.fieldId.getFieldName())) {
return field.fieldId;
}
}
throw new IllegalStateException("Field not found: " + fieldName);
}
private Object getFieldValue(TBase struct, TFieldIdEnum fieldId) {
TFieldIdEnum fieldRef = struct.fieldForId(fieldId.getThriftFieldId());
if (struct.isSet(fieldRef)) {
return struct.getFieldValue(fieldRef);
} else {
return null;
}
}
}