blob: 6616ca0726c7ffb2f7ad9f2ee2e5b351bcdc7597 [file] [log] [blame]
/*
* Copyright (C) 2018 Igalia, S.L.
* Copyright (C) 2018 Metrological Group B.V.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#if USE(GSTREAMER)
#include "GStreamerTest.h"
#include "Test.h"
#include <WebCore/GStreamerCommon.h>
#include <WebCore/SharedBuffer.h>
using namespace WebCore;
namespace TestWebKitAPI {
TEST_F(GStreamerTest, mappedBufferBasics)
{
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new_allocate(nullptr, 64, nullptr));
GstMappedBuffer mappedBuf(buf, GST_MAP_READ);
ASSERT_TRUE(mappedBuf);
EXPECT_EQ(mappedBuf.size(), 64);
GstMappedBuffer mappedBuf2(buf, GST_MAP_READ);
ASSERT_TRUE(mappedBuf2);
EXPECT_EQ(mappedBuf, mappedBuf2);
EXPECT_EQ(buf.get(), mappedBuf);
EXPECT_EQ(mappedBuf2, buf.get());
}
TEST_F(GStreamerTest, mappedBufferReadSanity)
{
gpointer memory = g_malloc(16);
memset(memory, 'x', 16);
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new_wrapped(memory, 16));
GstMappedBuffer mappedBuf(buf, GST_MAP_READ);
ASSERT_TRUE(mappedBuf);
EXPECT_EQ(mappedBuf.size(), 16);
EXPECT_EQ(memcmp(memory, mappedBuf.data(), 16), 0);
}
TEST_F(GStreamerTest, mappedBufferWriteSanity)
{
gpointer memory = g_malloc(16);
memset(memory, 'x', 16);
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new_wrapped(memory, 16));
GstMappedBuffer mappedBuf(buf.get(), GST_MAP_WRITE);
ASSERT_TRUE(mappedBuf);
EXPECT_EQ(mappedBuf.size(), 16);
memset(mappedBuf.data(), 'y', mappedBuf.size());
EXPECT_EQ(memcmp(memory, mappedBuf.data(), 16), 0);
}
TEST_F(GStreamerTest, mappedBufferDoesNotAddExtraRefs)
{
// It is important not to ref the passed GStreamer buffers, if we
// do so, then in the case of writable buffers, they can become
// unwritable, even though we are the sole owners. We also don't
// want to take ownership of the buffer from the user-code, since
// for transformInPlace use-cases, that would break.
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new());
ASSERT_EQ(GST_OBJECT_REFCOUNT(buf.get()), 1);
GstMappedBuffer mappedBuf(buf, GST_MAP_READWRITE);
ASSERT_TRUE(mappedBuf);
ASSERT_EQ(GST_OBJECT_REFCOUNT(buf.get()), 1);
}
TEST_F(GStreamerTest, mappedBufferValidityUnmapEarly)
{
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new());
GstMappedBuffer mappedBuf(buf, GST_MAP_READ);
ASSERT_TRUE(mappedBuf);
mappedBuf.unmapEarly();
ASSERT_FALSE(mappedBuf);
}
TEST_F(GStreamerTest, mappedOwnedBufferReadSanity)
{
gpointer memory = g_malloc(16);
memset(memory, 'x', 16);
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new_wrapped(memory, 16));
auto mappedBuf = GstMappedOwnedBuffer::create(buf);
ASSERT_TRUE(mappedBuf);
EXPECT_EQ(mappedBuf->size(), 16);
EXPECT_EQ(memcmp(memory, mappedBuf->data(), 16), 0);
EXPECT_EQ(memcmp(memory, mappedBuf->createSharedBuffer()->data(), 16), 0);
}
TEST_F(GStreamerTest, mappedOwnedBufferCachesSharedBuffers)
{
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new_allocate(nullptr, 64, nullptr));
auto mappedBuf = GstMappedOwnedBuffer::create(buf);
ASSERT_TRUE(mappedBuf);
auto sharedBuf = mappedBuf->createSharedBuffer();
// We expect the same data pointer wrapped by shared buffer, no
// copies need to be made.
EXPECT_EQ(sharedBuf->data(), mappedBuf->createSharedBuffer()->data());
}
TEST_F(GStreamerTest, mappedOwnedBufferDoesAddsExtraRefs)
{
// GstMappedOwnedBuffer needs to bump the buffer reference count
// so that it is sure that the buffer outlives the mapped buffer.
GRefPtr<GstBuffer> buf = adoptGRef(gst_buffer_new());
ASSERT_EQ(GST_OBJECT_REFCOUNT(buf.get()), 1);
{
auto mappedBuf = GstMappedOwnedBuffer::create(buf);
ASSERT_TRUE(mappedBuf);
ASSERT_EQ(GST_OBJECT_REFCOUNT(buf.get()), 2);
}
ASSERT_EQ(GST_OBJECT_REFCOUNT(buf.get()), 1);
}
TEST_F(GStreamerTest, mappedOwnedBufferDestruction)
{
GstBuffer* buffer = gst_buffer_new();
ASSERT_EQ(GST_OBJECT_REFCOUNT(buffer), 1);
auto mappedBuffer = GstMappedOwnedBuffer::create(buffer);
ASSERT_TRUE(mappedBuffer);
ASSERT_EQ(GST_OBJECT_REFCOUNT(buffer), 2);
// After this we should not use the buffer anymore but it should
// be still alive inside the mapped buffer, so we still can check
// the refcount.
gst_buffer_unref(buffer);
ASSERT_EQ(GST_OBJECT_REFCOUNT(buffer), 1);
// Now we are going to check if the buffer really outlives the
// mapped buffer. For that we check if there is no stderr output
// when we unref the mapped buffer. We can't check the ref count
// because it should be 0 and the object should be invalid, what
// could lead to a crash or other bad things.
char capturedStderrBuffer[BUFSIZ];
capturedStderrBuffer[0] = 0;
setbuf(stderr, capturedStderrBuffer);
mappedBuffer = nullptr;
setbuf(stderr, nullptr);
ASSERT_EQ(capturedStderrBuffer[0], 0);
}
} // namespace TestWebKitAPI
#endif // USE(GSTREAMER)