// Path: cocaine-core/src/main/java/cocaine/message/Message.java
// public abstract class Message {
// 
//     private static final long SYSTEM_SESSION = 0L;
// 
//     private final MessageType type;
//     private final long session;
// 
//     protected Message(MessageType type, long session) {
//         this.type = type;
//         this.session = session;
//     }
// 
//     protected Message(MessageType type) {
//         this(type, SYSTEM_SESSION);
//     }
// 
//     public MessageType getType() {
//         return type;
//     }
// 
//     public long getSession() {
//         return session;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || getClass() != o.getClass()) {
//             return false;
//         }
// 
//         Message message = (Message) o;
//         return session == message.session && type == message.type;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = type.hashCode();
//         result = 31 * result + (int) (session ^ (session >>> 32));
//         return result;
//     }
// 
// }
// 
// Path: cocaine-core/src/main/java/cocaine/message/Messages.java
// public final class Messages {
// 
//     public static Message handshake(UUID id) {
//         return new HandshakeMessage(id);
//     }
// 
//     public static Message heartbeat() {
//         return new HeartbeatMessage();
//     }
// 
//     public static Message terminate(TerminateMessage.Reason reason, String message) {
//         return new TerminateMessage(reason, message);
//     }
// 
//     public static Message invoke(long session, String event) {
//         return new InvokeMessage(session, event);
//     }
// 
//     public static Message chunk(long session, byte[] data) {
//         return new ChunkMessage(session, data);
//     }
// 
//     public static Message choke(long session) {
//         return new ChokeMessage(session);
//     }
// 
//     public static Message error(long session, int code, String message) {
//         return new ErrorMessage(session, code, message);
//     }
// 
//     private Messages() { }
// }
// 
// Path: cocaine-core/src/main/java/cocaine/message/TerminateMessage.java
// public final class TerminateMessage extends Message {
// 
//     public static enum Reason {
// 
//         NORMAL(1),
//         ABNORMAL(2),
//         ;
// 
//         private static final Map<Integer, Reason> mapping =
//                 Maps.uniqueIndex(Arrays.asList(Reason.values()), Reason.valueF());
// 
//         private final int value;
// 
//         private Reason(int value) {
//             this.value = value;
//         }
// 
//         public int value() {
//             return value;
//         }
// 
//         public static Reason fromValue(int value) {
//             Reason result = mapping.get(value);
//             if (result == null) {
//                 throw new IllegalArgumentException("Reason " + value + " does not exist");
//             }
//             return result;
//         }
// 
//         public static Function<Reason, Integer> valueF() {
//             return new Function<Reason, Integer>() {
//                 @Override
//                 public Integer apply(Reason reason) {
//                     return reason.value();
//                 }
//             };
//         }
//     }
// 
//     private final Reason reason;
//     private final String message;
// 
//     public TerminateMessage(Reason reason, String message) {
//         super(MessageType.TERMINATE);
//         this.reason = Preconditions.checkNotNull(reason, "Termination reason can not be null");
//         this.message = Preconditions.checkNotNull(message, "Message can not be null");
//     }
// 
//     public Reason getReason() {
//         return reason;
//     }
// 
//     public String getMessage() {
//         return message;
//     }
// 
//     @Override
//     public String toString() {
//         return "TerminateMessage/" + getSession() + ": " + reason.name() + " - " + message;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || getClass() != o.getClass()) {
//             return false;
//         }
//         if (!super.equals(o)) {
//             return false;
//         }
// 
//         TerminateMessage that = (TerminateMessage) o;
//         return message.equals(that.message) && reason == that.reason;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = super.hashCode();
//         result = 31 * result + reason.hashCode();
//         result = 31 * result + message.hashCode();
//         return result;
//     }
// 
// }


import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.UUID;
import cocaine.message.Message;
import cocaine.message.Messages;
import cocaine.message.TerminateMessage;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.msgpack.MessagePack;

        byte[] result = pack.write(msg, MessageTemplate.getInstance());

        Assert.assertArrayEquals(bytes, result);
    }

    @Test
    public void readHandshakeMessage() throws IOException {
        UUID uuid = UUID.randomUUID();
        Message msg = Messages.handshake(uuid);
        byte[] bytes = pack.write(Arrays.asList(0, 0, Arrays.asList(uuid)));

        Message result = pack.read(bytes, MessageTemplate.getInstance());

        Assert.assertEquals(msg, result);
    }

    @Test
    public void readHeartbeatMessage() throws IOException {
        Message msg = Messages.heartbeat();
        byte[] bytes = pack.write(Arrays.asList(1, 0, Arrays.asList()));

        Message result = pack.read(bytes, MessageTemplate.getInstance());

        Assert.assertEquals(msg, result);
    }

    @Test
    public void readTerminateMessage() throws IOException {
        String message = "PANIC!";
// Path: cocaine-core/src/main/java/cocaine/message/Message.java
// public abstract class Message {
// 
//     private static final long SYSTEM_SESSION = 0L;
// 
//     private final MessageType type;
//     private final long session;
// 
//     protected Message(MessageType type, long session) {
//         this.type = type;
//         this.session = session;
//     }
// 
//     protected Message(MessageType type) {
//         this(type, SYSTEM_SESSION);
//     }
// 
//     public MessageType getType() {
//         return type;
//     }
// 
//     public long getSession() {
//         return session;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || getClass() != o.getClass()) {
//             return false;
//         }
// 
//         Message message = (Message) o;
//         return session == message.session && type == message.type;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = type.hashCode();
//         result = 31 * result + (int) (session ^ (session >>> 32));
//         return result;
//     }
// 
// }
// 
// Path: cocaine-core/src/main/java/cocaine/message/Messages.java
// public final class Messages {
// 
//     public static Message handshake(UUID id) {
//         return new HandshakeMessage(id);
//     }
// 
//     public static Message heartbeat() {
//         return new HeartbeatMessage();
//     }
// 
//     public static Message terminate(TerminateMessage.Reason reason, String message) {
//         return new TerminateMessage(reason, message);
//     }
// 
//     public static Message invoke(long session, String event) {
//         return new InvokeMessage(session, event);
//     }
// 
//     public static Message chunk(long session, byte[] data) {
//         return new ChunkMessage(session, data);
//     }
// 
//     public static Message choke(long session) {
//         return new ChokeMessage(session);
//     }
// 
//     public static Message error(long session, int code, String message) {
//         return new ErrorMessage(session, code, message);
//     }
// 
//     private Messages() { }
// }
// 
// Path: cocaine-core/src/main/java/cocaine/message/TerminateMessage.java
// public final class TerminateMessage extends Message {
// 
//     public static enum Reason {
// 
//         NORMAL(1),
//         ABNORMAL(2),
//         ;
// 
//         private static final Map<Integer, Reason> mapping =
//                 Maps.uniqueIndex(Arrays.asList(Reason.values()), Reason.valueF());
// 
//         private final int value;
// 
//         private Reason(int value) {
//             this.value = value;
//         }
// 
//         public int value() {
//             return value;
//         }
// 
//         public static Reason fromValue(int value) {
//             Reason result = mapping.get(value);
//             if (result == null) {
//                 throw new IllegalArgumentException("Reason " + value + " does not exist");
//             }
//             return result;
//         }
// 
//         public static Function<Reason, Integer> valueF() {
//             return new Function<Reason, Integer>() {
//                 @Override
//                 public Integer apply(Reason reason) {
//                     return reason.value();
//                 }
//             };
//         }
//     }
// 
//     private final Reason reason;
//     private final String message;
// 
//     public TerminateMessage(Reason reason, String message) {
//         super(MessageType.TERMINATE);
//         this.reason = Preconditions.checkNotNull(reason, "Termination reason can not be null");
//         this.message = Preconditions.checkNotNull(message, "Message can not be null");
//     }
// 
//     public Reason getReason() {
//         return reason;
//     }
// 
//     public String getMessage() {
//         return message;
//     }
// 
//     @Override
//     public String toString() {
//         return "TerminateMessage/" + getSession() + ": " + reason.name() + " - " + message;
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) {
//             return true;
//         }
//         if (o == null || getClass() != o.getClass()) {
//             return false;
//         }
//         if (!super.equals(o)) {
//             return false;
//         }
// 
//         TerminateMessage that = (TerminateMessage) o;
//         return message.equals(that.message) && reason == that.reason;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = super.hashCode();
//         result = 31 * result + reason.hashCode();
//         result = 31 * result + message.hashCode();
//         return result;
//     }
// 
// }


// Path: cocaine-core/src/test/java/cocaine/msgpack/MessageTemplateTest.java
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.UUID;
import cocaine.message.Message;
import cocaine.message.Messages;
import cocaine.message.TerminateMessage;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.msgpack.MessagePack;


        byte[] result = pack.write(msg, MessageTemplate.getInstance());

        Assert.assertArrayEquals(bytes, result);
    }

    @Test
    public void readHandshakeMessage() throws IOException {
        UUID uuid = UUID.randomUUID();
        Message msg = Messages.handshake(uuid);
        byte[] bytes = pack.write(Arrays.asList(0, 0, Arrays.asList(uuid)));

        Message result = pack.read(bytes, MessageTemplate.getInstance());

        Assert.assertEquals(msg, result);
    }

    @Test
    public void readHeartbeatMessage() throws IOException {
        Message msg = Messages.heartbeat();
        byte[] bytes = pack.write(Arrays.asList(1, 0, Arrays.asList()));

        Message result = pack.read(bytes, MessageTemplate.getInstance());

        Assert.assertEquals(msg, result);
    }

    @Test
    public void readTerminateMessage() throws IOException {
        String message = "PANIC!";
        Message msg = Messages.terminate(TerminateMessage.Reason.NORMAL, message);