/* * 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.flink.api.common.typeutils; import org.apache.flink.core.memory.DataInputView; import org.apache.flink.core.memory.DataInputViewStreamWrapper; import org.apache.flink.core.memory.DataOutputView; import org.apache.flink.core.memory.DataOutputViewStreamWrapper; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.net.URLClassLoader; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; /** * Unit tests related to {@link TypeSerializerConfigSnapshot}. */ public class TypeSerializerConfigSnapshotTest { /** * Verifies that reading and writing configuration snapshots work correctly. */ @Test public void testSerializeConfigurationSnapshots() throws Exception { TestConfigSnapshot configSnapshot1 = new TestConfigSnapshot(1, "foo"); TestConfigSnapshot configSnapshot2 = new TestConfigSnapshot(2, "bar"); byte[] serializedConfig; try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { TypeSerializerUtil.writeSerializerConfigSnapshots( new DataOutputViewStreamWrapper(out), configSnapshot1, configSnapshot2); serializedConfig = out.toByteArray(); } TypeSerializerConfigSnapshot[] restoredConfigs; try (ByteArrayInputStream in = new ByteArrayInputStream(serializedConfig)) { restoredConfigs = TypeSerializerUtil.readSerializerConfigSnapshots( new DataInputViewStreamWrapper(in), Thread.currentThread().getContextClassLoader()); } assertEquals(2, restoredConfigs.length); assertEquals(configSnapshot1, restoredConfigs[0]); assertEquals(configSnapshot2, restoredConfigs[1]); } /** * Verifies that deserializing config snapshots fail if the config class could not be found. */ @Test public void testFailsWhenConfigurationSnapshotClassNotFound() throws Exception { byte[] serializedConfig; try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { TypeSerializerUtil.writeSerializerConfigSnapshot( new DataOutputViewStreamWrapper(out), new TestConfigSnapshot(123, "foobar")); serializedConfig = out.toByteArray(); } try (ByteArrayInputStream in = new ByteArrayInputStream(serializedConfig)) { // read using a dummy classloader TypeSerializerUtil.readSerializerConfigSnapshot( new DataInputViewStreamWrapper(in), new URLClassLoader(new URL[0], null)); fail("Expected a ClassNotFoundException wrapped in IOException"); } catch (IOException expected) { // test passes } } public static class TestConfigSnapshot extends TypeSerializerConfigSnapshot { static final int VERSION = 1; private int val; private String msg; public TestConfigSnapshot() {} public TestConfigSnapshot(int val, String msg) { this.val = val; this.msg = msg; } @Override public void write(DataOutputView out) throws IOException { super.write(out); out.writeInt(val); out.writeUTF(msg); } @Override public void read(DataInputView in) throws IOException { super.read(in); val = in.readInt(); msg = in.readUTF(); } @Override public int getVersion() { return VERSION; } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (obj == null) { return false; } if (obj instanceof TestConfigSnapshot) { return val == ((TestConfigSnapshot) obj).val && msg.equals(((TestConfigSnapshot) obj).msg); } else { return false; } } @Override public int hashCode() { return 31 * val + msg.hashCode(); } } }