<commit_before>/**
 * 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.qpid.jms.provider.amqp.message;

import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_BYTES_MESSAGE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_MSG_TYPE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.getSymbol;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
import org.apache.qpid.proton.amqp.messaging.AmqpValue;
import org.apache.qpid.proton.amqp.messaging.Data;
import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
import org.apache.qpid.proton.message.Message;
import org.junit.Ignore;
import org.junit.Test;

/**
 * Tests for class AmqpJmsBytesMessageFacade
 */
public class AmqpJmsBytesMessageFacadeTest extends AmqpJmsMessageTypesTestCase {

    private static final int END_OF_STREAM = -1;

    // ---------- Test initial state of newly created message -----------------//

    @Test
    public void testNewMessageContainsMessageTypeAnnotation() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();
        MessageAnnotations annotations = protonMessage.getMessageAnnotations();
        Map<Symbol, Object> annotationsMap = annotations.getValue();

        assertNotNull("MessageAnnotations section was not present", annotations);
        assertNotNull("MessageAnnotations section value was not present", annotationsMap);

        assertTrue("expected message type annotation to be present", annotationsMap.containsKey(AmqpMessageSupport.getSymbol(JMS_MSG_TYPE)));
        assertEquals("unexpected value for message type annotation value", JMS_BYTES_MESSAGE, annotationsMap.get(getSymbol(JMS_MSG_TYPE)));
        assertEquals(JMS_BYTES_MESSAGE, amqpBytesMessageFacade.getJmsMsgType());
    }

    @Test
    public void testGetInputStreamWithNewMessageReturnsEmptyInputStream() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        InputStream byteArrayInputStream = amqpBytesMessageFacade.getInputStream();
        assertNotNull(byteArrayInputStream);

        // try to read a byte, it should return -1 bytes read, i.e EOS.
        assertEquals("Expected input stream to be at end but data was returned", END_OF_STREAM, byteArrayInputStream.read(new byte[1]));
    }

    @Test
    public void testGetBodyLengthUsingNewMessage() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        assertEquals("Message reports unexpected length", 0, amqpBytesMessageFacade.getBodyLength());
    }

    @Test
    public void testNewMessageHasContentTypeButNoBodySection() throws Exception {
        // TODO: this test assumes we can omit the body section. If we decide otherwise
        // it should instead check for e.g. a data section containing 0 length binary
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();
        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();

        assertNotNull(protonMessage);
        assertNull(protonMessage.getBody());

        String contentType = protonMessage.getContentType();
        assertNotNull("content type should be set", contentType);
        assertEquals("application/octet-stream", contentType);
    }

    // ---------- test for normal message operations -------------------------//

    @Test
    public void testGetBodyLengthUsingPopulatedMessageToSend() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        byte[] bytes = "myBytes".getBytes();
        amqpBytesMessageFacade.setBody(bytes);

        assertEquals("Message reports unexpected length", bytes.length, amqpBytesMessageFacade.getBodyLength());
    }

    /**
     * Test that setting bytes on a new messages creates the data section of the underlying message,
     * which as tested by {@link #testNewMessageHasContentTypeButNoBodySection} does not exist initially.
     */
    @Test
    public void testSetBodyOnNewMessageCreatesDataSection() throws Exception {
        byte[] testBytes = "myTestBytes".getBytes();
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();
        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();

        assertNotNull("underlying proton message was null", protonMessage);
        assertNull("Expected no body section to be present", protonMessage.getBody());

        amqpBytesMessageFacade.setBody(testBytes);

        assertNotNull("Expected body section to be present", protonMessage.getBody());
        assertEquals("Unexpected body section type", Data.class, protonMessage.getBody().getClass());
    }

    /**
     * Test that setting bytes on a new message results in the expected content in the body section
     * of the underlying message and returned by a new InputStream requested from the message.
     */
    @Test
    public void testSetGetBytesOnNewMessage() throws Exception {
        byte[] bytes = "myTestBytes".getBytes();
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();
        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();

        amqpBytesMessageFacade.setBody(bytes);

        // retrieve the bytes from the underlying message, check they match
        Data body = (Data) protonMessage.getBody();
        assertTrue("Underlying message data section did not contain the expected bytes", Arrays.equals(bytes, body.getValue().getArray()));

        // retrieve the bytes via an InputStream, check they match expected
        byte[] receivedBytes = new byte[bytes.length];
        InputStream bytesStream = amqpBytesMessageFacade.getInputStream();
        bytesStream.read(receivedBytes);
        assertTrue("Retrieved bytes from input steam did not match expected bytes", Arrays.equals(bytes, receivedBytes));

        // verify no more bytes remain, i.e EOS
        assertEquals("Expected input stream to be at end but data was returned", END_OF_STREAM, bytesStream.read(new byte[1]));
    }

    // ---------- test handling of received messages -------------------------//

    @Test
    public void testGetInputStreamUsingReceivedMessageWithNoBodySectionReturnsEmptyInputStream() throws Exception {
        Message message = Message.Factory.create();
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createReceivedBytesMessageFacade(createMockAmqpConsumer(), message);

        InputStream byteArrayInputStream = amqpBytesMessageFacade.getInputStream();
        assertNotNull(byteArrayInputStream);

        // try to read a byte, it should return -1 bytes read, i.e EOS.
        assertEquals("Expected input stream to be at end but data was returned", END_OF_STREAM, byteArrayInputStream.read(new byte[1]));
    }

    @Test
    public void testGetBodyLengthUsingReceivedMessageWithDataSectionContainingNonZeroLengthBinary() throws Exception {
        Message message = Message.Factory.create();
        int length = 5;
        message.setBody(new Data(new Binary(new byte[length])));
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createReceivedBytesMessageFacade(createMockAmqpConsumer(), message);

        assertEquals("Message reports unexpected length", length, amqpBytesMessageFacade.getBodyLength());
    }

    @Test
    public void testGetBodyLengthUsingReceivedMessageWithAmqpValueSectionContainingNonZeroLengthBinary() throws Exception {
        Message message = Message.Factory.create();
        int length = 10;
        message.setBody(new AmqpValue(new Binary(new byte[length])));<commit_msg>add some more unit tests for AmqpJmsBytesMessageFacade<commit_after>/**
 * 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.qpid.jms.provider.amqp.message;

import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_BYTES_MESSAGE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.JMS_MSG_TYPE;
import static org.apache.qpid.jms.provider.amqp.message.AmqpMessageSupport.getSymbol;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.AmqpSequence;
import org.apache.qpid.proton.amqp.messaging.AmqpValue;
import org.apache.qpid.proton.amqp.messaging.Data;
import org.apache.qpid.proton.amqp.messaging.MessageAnnotations;
import org.apache.qpid.proton.amqp.messaging.Section;
import org.apache.qpid.proton.message.Message;
import org.junit.Ignore;
import org.junit.Test;

/**
 * Tests for class AmqpJmsBytesMessageFacade
 */
public class AmqpJmsBytesMessageFacadeTest extends AmqpJmsMessageTypesTestCase {

    private static final int END_OF_STREAM = -1;

    // ---------- Test initial state of newly created message -----------------//

    @Test
    public void testNewMessageContainsMessageTypeAnnotation() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();
        MessageAnnotations annotations = protonMessage.getMessageAnnotations();
        Map<Symbol, Object> annotationsMap = annotations.getValue();

        assertNotNull("MessageAnnotations section was not present", annotations);
        assertNotNull("MessageAnnotations section value was not present", annotationsMap);

        assertTrue("expected message type annotation to be present", annotationsMap.containsKey(AmqpMessageSupport.getSymbol(JMS_MSG_TYPE)));
        assertEquals("unexpected value for message type annotation value", JMS_BYTES_MESSAGE, annotationsMap.get(getSymbol(JMS_MSG_TYPE)));
        assertEquals(JMS_BYTES_MESSAGE, amqpBytesMessageFacade.getJmsMsgType());
    }

    @Test
    public void testGetInputStreamWithNewMessageReturnsEmptyInputStream() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        InputStream byteArrayInputStream = amqpBytesMessageFacade.getInputStream();
        assertNotNull(byteArrayInputStream);

        // try to read a byte, it should return -1 bytes read, i.e EOS.
        assertEquals("Expected input stream to be at end but data was returned", END_OF_STREAM, byteArrayInputStream.read(new byte[1]));
    }

    @Test
    public void testGetBodyLengthUsingNewMessage() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        assertEquals("Message reports unexpected length", 0, amqpBytesMessageFacade.getBodyLength());
    }

    @Test
    public void testNewMessageHasContentTypeButNoBodySection() throws Exception {
        // TODO: this test assumes we can omit the body section. If we decide otherwise
        // it should instead check for e.g. a data section containing 0 length binary
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();
        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();

        assertNotNull(protonMessage);
        assertNull(protonMessage.getBody());

        String contentType = protonMessage.getContentType();
        assertNotNull("content type should be set", contentType);
        assertEquals("application/octet-stream", contentType);
    }

    // ---------- test for normal message operations -------------------------//

    @Test
    public void testGetBodyLengthUsingPopulatedMessageToSend() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        byte[] bytes = "myBytes".getBytes();
        amqpBytesMessageFacade.setBody(bytes);

        assertEquals("Message reports unexpected length", bytes.length, amqpBytesMessageFacade.getBodyLength());
    }

    /**
     * Test that setting bytes on a new messages creates the data section of the underlying message,
     * which as tested by {@link #testNewMessageHasContentTypeButNoBodySection} does not exist initially.
     */
    @Test
    public void testSetBodyOnNewMessageCreatesDataSection() throws Exception {
        byte[] testBytes = "myTestBytes".getBytes();
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();
        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();

        assertNotNull("underlying proton message was null", protonMessage);
        assertNull("Expected no body section to be present", protonMessage.getBody());

        amqpBytesMessageFacade.setBody(testBytes);

        assertNotNull("Expected body section to be present", protonMessage.getBody());
        assertEquals("Unexpected body section type", Data.class, protonMessage.getBody().getClass());
    }

    /**
     * Test that setting bytes on a new message results in the expected content in the body section
     * of the underlying message and returned by a new InputStream requested from the message.
     */
    @Test
    public void testSetGetBytesOnNewMessage() throws Exception {
        byte[] bytes = "myTestBytes".getBytes();
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();
        Message protonMessage = amqpBytesMessageFacade.getAmqpMessage();

        amqpBytesMessageFacade.setBody(bytes);

        // retrieve the bytes from the underlying message, check they match
        Data body = (Data) protonMessage.getBody();
        assertTrue("Underlying message data section did not contain the expected bytes", Arrays.equals(bytes, body.getValue().getArray()));

        // retrieve the bytes via an InputStream, check they match expected
        byte[] receivedBytes = new byte[bytes.length];
        InputStream bytesStream = amqpBytesMessageFacade.getInputStream();
        bytesStream.read(receivedBytes);
        assertTrue("Retrieved bytes from input steam did not match expected bytes", Arrays.equals(bytes, receivedBytes));

        // verify no more bytes remain, i.e EOS
        assertEquals("Expected input stream to be at end but data was returned", END_OF_STREAM, bytesStream.read(new byte[1]));
    }

    @Test
    public void testClearBodySetsBodyLength0AndCausesEmptyInputStream() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        byte[] bytes = "myBytes".getBytes();
        amqpBytesMessageFacade.setBody(bytes);
        amqpBytesMessageFacade.clearBody();

        amqpBytesMessageFacade.clearBody();
        assertTrue("Expected no message content from facade", amqpBytesMessageFacade.getBodyLength() == 0);
        assertEquals("Expected no data from facade, but got some", END_OF_STREAM, amqpBytesMessageFacade.getInputStream().read(new byte[1]));

        Section body = amqpBytesMessageFacade.getAmqpMessage().getBody();
        assertTrue(body instanceof Data);
        Binary value = ((Data) body).getValue();
        assertNotNull(value);
        assertEquals(0, value.getLength());
    }

    @Test
    public void testClearBodyWithExistingInputStream() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        byte[] bytes = "myBytes".getBytes();
        amqpBytesMessageFacade.setBody(bytes);

        @SuppressWarnings("unused")
        InputStream unused = amqpBytesMessageFacade.getInputStream();

        amqpBytesMessageFacade.clearBody();

        assertEquals("Expected no data from facade, but got some", END_OF_STREAM, amqpBytesMessageFacade.getInputStream().read(new byte[1]));

        Section body = amqpBytesMessageFacade.getAmqpMessage().getBody();
        assertTrue(body instanceof Data);
        Binary value = ((Data) body).getValue();
        assertNotNull(value);
        assertEquals(0, value.getLength());
    }

    @Test
    public void testClearBodyWithExistingOutputStream() throws Exception {
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createNewBytesMessageFacade();

        byte[] bytes = "myBytes".getBytes();
        amqpBytesMessageFacade.setBody(bytes);

        @SuppressWarnings("unused")
        OutputStream unused = amqpBytesMessageFacade.getOutputStream();

        amqpBytesMessageFacade.clearBody();

        Section body = amqpBytesMessageFacade.getAmqpMessage().getBody();
        assertTrue(body instanceof Data);
        Binary value = ((Data) body).getValue();
        assertNotNull(value);
        assertEquals(0, value.getLength());
    }

    // ---------- test handling of received messages -------------------------//

    @Test
    public void testGetInputStreamUsingReceivedMessageWithNoBodySectionReturnsEmptyInputStream() throws Exception {
        Message message = Message.Factory.create();
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createReceivedBytesMessageFacade(createMockAmqpConsumer(), message);

        InputStream byteArrayInputStream = amqpBytesMessageFacade.getInputStream();
        assertNotNull(byteArrayInputStream);

        // try to read a byte, it should return -1 bytes read, i.e EOS.
        assertEquals("Expected input stream to be at end but data was returned", END_OF_STREAM, byteArrayInputStream.read(new byte[1]));
    }

    @Test
    public void testGetBodyLengthUsingReceivedMessageWithDataSectionContainingNonZeroLengthBinary() throws Exception {
        Message message = Message.Factory.create();
        int length = 5;
        message.setBody(new Data(new Binary(new byte[length])));
        AmqpJmsBytesMessageFacade amqpBytesMessageFacade = createReceivedBytesMessageFacade(createMockAmqpConsumer(), message);

        assertEquals("Message reports unexpected length", length, amqpBytesMessageFacade.getBodyLength());
    }

    @Test
    public void testGetBodyLengthUsingReceivedMessageWithAmqpValueSectionContainingNonZeroLengthBinary() throws Exception {
        Message message = Message.Factory.create();
        int length = 10;
        message.setBody(new AmqpValue(new Binary(new byte[length])));
{'fraction_non_alphanumeric': 0.08920856245090338, 'fraction_numerical': 0.001816575019638649, 'mean_word_length': 3.9439320388349515, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3146800', 'n_tokens_mistral': 5214, 'n_tokens_neox': 5061, 'n_words': 1435}