/** * diqube: Distributed Query Base. * * Copyright (C) 2015 Bastian Gloeckle * * This file is part of diqube. * * diqube is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.diqube.connection.integrity; import org.apache.thrift.TException; import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.protocol.TMessage; import org.apache.thrift.transport.TMemoryBuffer; import org.apache.thrift.transport.TMemoryInputTransport; import org.diqube.connection.integrity.IntegrityCheckingProtocol.IntegrityViolatedException; import org.diqube.thrift.util.RememberingTransport; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * * @author Bastian Gloeckle */ public class IntegrityCheckingProtocolTest { private static final byte[][] MAC_KEYS = new byte[][] { new byte[] { 0x01, 0x02, 0x03 } }; private IntegrityCheckingProtocol outputIntegrityValidatingProtocol; private TMemoryBuffer outputMemoryBuf; private TMemoryInputTransport inputMemoryTrans; private IntegrityCheckingProtocol inputIntegrityValidatingProtocol; @BeforeMethod public void before() { outputMemoryBuf = new TMemoryBuffer(0); TBinaryProtocol outputBinaryProtocol = new TBinaryProtocol(new RememberingTransport(outputMemoryBuf)); outputIntegrityValidatingProtocol = new IntegrityCheckingProtocol(outputBinaryProtocol, MAC_KEYS); inputMemoryTrans = new TMemoryInputTransport(); TBinaryProtocol inputBinaryProtocol = new TBinaryProtocol(new RememberingTransport(inputMemoryTrans)); inputIntegrityValidatingProtocol = new IntegrityCheckingProtocol(inputBinaryProtocol, MAC_KEYS); } @AfterMethod public void after() { } @Test public void sendAndReceive() throws TException { // GIVEN TMessage msg = new TMessage("a", (byte) 0, 0); int content = 100; outputIntegrityValidatingProtocol.writeMessageBegin(msg); outputIntegrityValidatingProtocol.writeI32(content); outputIntegrityValidatingProtocol.writeMessageEnd(); inputMemoryTrans.reset(outputMemoryBuf.getArray(), 0, outputMemoryBuf.length()); // WHEN TMessage readMsg = inputIntegrityValidatingProtocol.readMessageBegin(); int readContent = inputIntegrityValidatingProtocol.readI32(); inputIntegrityValidatingProtocol.readMessageEnd(); // THEN Assert.assertEquals(readMsg, msg, "Expected to read correct TMessage"); Assert.assertEquals(content, readContent, "Expected to read correct content"); // and: Expected not to have a validity exception! } @Test(expectedExceptions = IntegrityViolatedException.class) public void sendAndReceiveTamperedMessage() throws TException { // GIVEN TMessage msg = new TMessage("a", (byte) 0, 0); int content = 100; outputIntegrityValidatingProtocol.writeMessageBegin(msg); outputIntegrityValidatingProtocol.writeI32(content); outputIntegrityValidatingProtocol.writeMessageEnd(); byte[] wireData = outputMemoryBuf.getArray(); // tamper with the message on the wire wireData[wireData.length / 2] = (byte) -wireData[wireData.length / 2]; inputMemoryTrans.reset(wireData); // WHEN inputIntegrityValidatingProtocol.readMessageBegin(); inputIntegrityValidatingProtocol.readI32(); inputIntegrityValidatingProtocol.readMessageEnd(); // THEN // and: Expected to have a validity exception! } @Test public void noSideeffects() throws TException { // GIVEN TMessage msg = new TMessage("a", (byte) 0, 0); int content = 100; outputIntegrityValidatingProtocol.writeMessageBegin(msg); outputIntegrityValidatingProtocol.writeI32(content); outputIntegrityValidatingProtocol.writeMessageEnd(); int intermediaryPos = outputMemoryBuf.length(); // WHEN outputIntegrityValidatingProtocol.writeMessageBegin(msg); outputIntegrityValidatingProtocol.writeI32(content); outputIntegrityValidatingProtocol.writeMessageEnd(); // THEN byte[] firstMsg = new byte[intermediaryPos]; byte[] secondMsg = new byte[outputMemoryBuf.length() - intermediaryPos]; System.arraycopy(outputMemoryBuf.getArray(), 0, firstMsg, 0, intermediaryPos); System.arraycopy(outputMemoryBuf.getArray(), intermediaryPos, secondMsg, 0, secondMsg.length); Assert.assertEquals(firstMsg, secondMsg, "Expected that first and second message are encoded in the same way!"); } }