blob: 11e727be812be884610358256f554f89be4e9e17 [file] [log] [blame]
/*
* 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.geode.internal;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import junit.framework.TestCase;
import org.junit.After;
import org.junit.Test;
import org.apache.geode.DataSerializer;
public class DataSerializerHolderJUnitTest extends TestCase {
@Override
@After
public void tearDown() {
InternalDataSerializer.reinitialize();
}
@Test
public void testHandshakeDatSerializerRegistrationDoesNotHitNPE() throws Throwable {
// a thread performing a handshake from the client side may receive a list of
// DataSerializer class names. It registers these with InternalDataSerializer to
// create placeholders for later lazy loading of the classes
Class[] serializers = new Class[] {DataSerializer1.class, DataSerializer2.class,
DataSerializer3.class, DataSerializer4.class, DataSerializer5.class, DataSerializer6.class,
DataSerializer7.class, DataSerializer8.class, DataSerializer9.class, DataSerializer10.class,
DataSerializer11.class, DataSerializer12.class, DataSerializer13.class};
for (int index = 0; index < serializers.length; index++) {
int id = InternalDataSerializer.newInstance(serializers[index]).getId();
InternalDataSerializer.register(serializers[index].getName(), false, null, null, id);
}
// The thread will then register classes handled by the DataSerializers, but if
// getSerializers() or a similar method is invoked by some other thread first the
// placeholders will be wiped out, causing an NPE when registering the handled
// classes. The NPE is caused by the placeholder being null in updateSupportedClassesMap().
// Here we avoid creating a multithreaded test by invoking getSerializers() in-line
InternalDataSerializer.getSerializers();
// Now we perform the second step in the handshake code of registering the classes
// handled by the DataSerializers. Without the bugfix this causes an NPE
Map<Integer, List<String>> supportedClasses = new HashMap<>();
for (int index = 0; index < serializers.length; index++) {
DataSerializer serializer = InternalDataSerializer.newInstance(serializers[index]);
List<String> classes = Arrays.<Class>asList(serializer.getSupportedClasses()).stream()
.map((clazz) -> clazz.getName()).collect(Collectors.toList());
supportedClasses.put(serializer.getId(), classes);
}
InternalDataSerializer.updateSupportedClassesMap(supportedClasses);
}
public static class DataSerializer1 extends DataSerializer {
int tempField = 5;
public DataSerializer1() {
}
@Override
public int getId() {
return 1;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {MyClass1.class, MyClass2.class, MyClass3.class, MyClass4.class,
MyClass5.class, MyClass6.class, MyClass7.class, MyClass8.class, MyClass9.class,
MyClass10.class};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
return true;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer2 extends DataSerializer {
int tempField = 15;
public DataSerializer2() {}
@Override
public int getId() {
return 2;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {MyClass11.class, MyClass12.class, MyClass13.class, MyClass14.class,
MyClass15.class, MyClass16.class, MyClass17.class, MyClass18.class, MyClass19.class,
MyClass20.class};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
return true;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer3 extends DataSerializer {
int tempField = 25;
public DataSerializer3() {}
@Override
public int getId() {
return 3;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer4 extends DataSerializer {
int tempField = 5;
public DataSerializer4() {
}
@Override
public int getId() {
return 4;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer5 extends DataSerializer {
int tempField = 15;
public DataSerializer5() {}
@Override
public int getId() {
return 5;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer6 extends DataSerializer {
int tempField = 25;
public DataSerializer6() {}
@Override
public int getId() {
return 6;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer7 extends DataSerializer {
int tempField = 5;
public DataSerializer7() {
}
@Override
public int getId() {
return 7;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer8 extends DataSerializer {
int tempField = 15;
public DataSerializer8() {}
@Override
public int getId() {
return 8;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer9 extends DataSerializer {
int tempField = 25;
public DataSerializer9() {}
@Override
public int getId() {
return 9;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer10 extends DataSerializer {
int tempField = 5;
public DataSerializer10() {
}
@Override
public int getId() {
return 10;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer11 extends DataSerializer {
int tempField = 15;
public DataSerializer11() {}
@Override
public int getId() {
return 11;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer12 extends DataSerializer {
int tempField = 25;
public DataSerializer12() {}
@Override
public int getId() {
return 12;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class DataSerializer13 extends DataSerializer {
int tempField = 25;
public DataSerializer13() {}
@Override
public int getId() {
return 19;
}
@Override
public Class[] getSupportedClasses() {
return new Class[] {this.getClass()};
}
@Override
public boolean toData(Object o, DataOutput out) throws IOException {
out.write(tempField);
return false;
}
@Override
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
readInteger(in);
return null;
}
}
public static class MyClass1 {
public MyClass1() {}
}
public static class MyClass2 {
public MyClass2() {}
}
public static class MyClass3 {
public MyClass3() {}
}
public static class MyClass4 {
public MyClass4() {}
}
public static class MyClass5 {
public MyClass5() {}
}
public static class MyClass6 {
public MyClass6() {}
}
public static class MyClass7 {
public MyClass7() {}
}
public static class MyClass8 {
public MyClass8() {}
}
public static class MyClass9 {
public MyClass9() {}
}
public static class MyClass10 {
public MyClass10() {}
}
public static class MyClass11 {
public MyClass11() {}
}
public static class MyClass12 {
public MyClass12() {}
}
public static class MyClass13 {
public MyClass13() {}
}
public static class MyClass14 {
public MyClass14() {}
}
public static class MyClass15 {
public MyClass15() {}
}
public static class MyClass16 {
public MyClass16() {}
}
public static class MyClass17 {
public MyClass17() {}
}
public static class MyClass18 {
public MyClass18() {}
}
public static class MyClass19 {
public MyClass19() {}
}
public static class MyClass20 {
public MyClass20() {}
}
}