/* * 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.kafka.streams.processor.internals.assignment; import org.apache.kafka.common.TopicPartition; import org.apache.kafka.common.utils.Utils; import org.apache.kafka.streams.processor.TaskId; import org.apache.kafka.streams.state.HostInfo; import org.junit.Test; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import static org.junit.Assert.assertEquals; public class AssignmentInfoTest { @Test public void testEncodeDecode() { List<TaskId> activeTasks = Arrays.asList(new TaskId(0, 0), new TaskId(0, 0), new TaskId(0, 1), new TaskId(1, 0)); Map<TaskId, Set<TopicPartition>> standbyTasks = new HashMap<>(); standbyTasks.put(new TaskId(1, 1), Utils.mkSet(new TopicPartition("t1", 1), new TopicPartition("t2", 1))); standbyTasks.put(new TaskId(2, 0), Utils.mkSet(new TopicPartition("t3", 0), new TopicPartition("t3", 0))); AssignmentInfo info = new AssignmentInfo(activeTasks, standbyTasks, new HashMap<HostInfo, Set<TopicPartition>>()); AssignmentInfo decoded = AssignmentInfo.decode(info.encode()); assertEquals(info, decoded); } @Test public void shouldDecodePreviousVersion() throws Exception { List<TaskId> activeTasks = Arrays.asList(new TaskId(0, 0), new TaskId(0, 0), new TaskId(0, 1), new TaskId(1, 0)); Map<TaskId, Set<TopicPartition>> standbyTasks = new HashMap<>(); standbyTasks.put(new TaskId(1, 1), Utils.mkSet(new TopicPartition("t1", 1), new TopicPartition("t2", 1))); standbyTasks.put(new TaskId(2, 0), Utils.mkSet(new TopicPartition("t3", 0), new TopicPartition("t3", 0))); final AssignmentInfo oldVersion = new AssignmentInfo(1, activeTasks, standbyTasks, null); final AssignmentInfo decoded = AssignmentInfo.decode(encodeV1(oldVersion)); assertEquals(oldVersion.activeTasks, decoded.activeTasks); assertEquals(oldVersion.standbyTasks, decoded.standbyTasks); assertEquals(0, decoded.partitionsByHost.size()); // should be empty as wasn't in V1 assertEquals(2, decoded.version); // automatically upgraded to v2 on decode; } /** * This is a clone of what the V1 encoding did. The encode method has changed for V2 * so it is impossible to test compatibility without having this */ private ByteBuffer encodeV1(AssignmentInfo oldVersion) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); DataOutputStream out = new DataOutputStream(baos); // Encode version out.writeInt(oldVersion.version); // Encode active tasks out.writeInt(oldVersion.activeTasks.size()); for (TaskId id : oldVersion.activeTasks) { id.writeTo(out); } // Encode standby tasks out.writeInt(oldVersion.standbyTasks.size()); for (Map.Entry<TaskId, Set<TopicPartition>> entry : oldVersion.standbyTasks.entrySet()) { TaskId id = entry.getKey(); id.writeTo(out); Set<TopicPartition> partitions = entry.getValue(); out.writeInt(partitions.size()); for (TopicPartition partition : partitions) { out.writeUTF(partition.topic()); out.writeInt(partition.partition()); } } out.flush(); out.close(); return ByteBuffer.wrap(baos.toByteArray()); } }