X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=blobdiff_plain;f=src%2Ftype3_AndroidCloud%2Fanbox-master%2Ftests%2Fanbox%2Fgraphics%2Fbuffer_queue_tests.cpp;fp=src%2Ftype3_AndroidCloud%2Fanbox-master%2Ftests%2Fanbox%2Fgraphics%2Fbuffer_queue_tests.cpp;h=38a391d4fa05a89588aa342eb7ba62b66cf0b565;hb=e26c1ec581be598521517829adba8c8dd23a768f;hp=0000000000000000000000000000000000000000;hpb=6699c1aea74eeb0eb400e6299079f0c7576f716f;p=iec.git diff --git a/src/type3_AndroidCloud/anbox-master/tests/anbox/graphics/buffer_queue_tests.cpp b/src/type3_AndroidCloud/anbox-master/tests/anbox/graphics/buffer_queue_tests.cpp new file mode 100644 index 0000000..38a391d --- /dev/null +++ b/src/type3_AndroidCloud/anbox-master/tests/anbox/graphics/buffer_queue_tests.cpp @@ -0,0 +1,298 @@ +// Copyright (C) 2016 The Android Open Source Project +// +// Licensed 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. + +#include "anbox/graphics/buffer_queue.h" +#include "anbox/common/message_channel.h" +#include "anbox/logger.h" + +#include + +#include + +namespace anbox { +namespace graphics { +TEST(BufferQueue, Constructor) { + BufferQueue queue(16); +} + +TEST(BufferQueue, TryPushLocked) { + BufferQueue queue(2); + + EXPECT_EQ(0, queue.try_push_locked(Buffer("Hello"))); + EXPECT_EQ(0, queue.try_push_locked(Buffer("World"))); + + Buffer buff0("You Shall Not Move"); + EXPECT_EQ(-EAGAIN, queue.try_push_locked(std::move(buff0))); + EXPECT_FALSE(buff0.empty()) << "Buffer should not be moved on failure!"; +} + +TEST(BufferQueue, TryPushLockedOnClosedQueue) { + BufferQueue queue(2); + + EXPECT_EQ(0, queue.try_push_locked(Buffer("Hello"))); + + // Closing the queue prevents pushing new items to the queue. + queue.close_locked(); + + EXPECT_EQ(-EIO, queue.try_push_locked(Buffer("World"))); +} + +TEST(BufferQueue, TryPopLocked) { + BufferQueue queue(2);; + + Buffer buffer; + EXPECT_EQ(-EAGAIN, queue.try_pop_locked(&buffer)); + + EXPECT_EQ(0, queue.try_push_locked(Buffer("Hello"))); + EXPECT_EQ(0, queue.try_push_locked(Buffer("World"))); + + EXPECT_EQ(0, queue.try_pop_locked(&buffer)); + EXPECT_STREQ("Hello", buffer.data()); + + EXPECT_EQ(0, queue.try_pop_locked(&buffer)); + EXPECT_STREQ("World", buffer.data()); + + EXPECT_EQ(-EAGAIN, queue.try_pop_locked(&buffer)); + EXPECT_STREQ("World", buffer.data()); +} + +TEST(BufferQueue, TryPopLockedOnClosedQueue) { + BufferQueue queue(2); + + Buffer buffer; + EXPECT_EQ(-EAGAIN, queue.try_pop_locked(&buffer)); + + EXPECT_EQ(0, queue.try_push_locked(Buffer("Hello"))); + EXPECT_EQ(0, queue.try_push_locked(Buffer("World"))); + + EXPECT_EQ(0, queue.try_pop_locked(&buffer)); + EXPECT_STREQ("Hello", buffer.data()); + + // Closing the queue doesn't prevent popping existing items, but + // will generate -EIO once it is empty. + queue.close_locked(); + + EXPECT_EQ(0, queue.try_pop_locked(&buffer)); + EXPECT_STREQ("World", buffer.data()); + + EXPECT_EQ(-EIO, queue.try_pop_locked(&buffer)); + EXPECT_STREQ("World", buffer.data()); +} + +namespace { +// A TestThread instance that holds a reference to a queue and can either +// push or pull to it, on command from another thread. This uses a +// MessageChannel to implement the communication channel between the +// command thread and this one. +class TestThread final { + public: + TestThread(std::mutex &lock, BufferQueue &queue) : + lock_(lock), + queue_(queue) { + } + + bool start() { + thread_ = std::thread(&TestThread::thread_main, this); + return true; + } + + // Tell the test thread to push |buffer| to the queue. + // Call endPush() later to get the command's result. + bool start_push(Buffer&& buffer) { + input_.send(Request{Cmd::Push, std::move(buffer)}); + return true; + } + + int end_push() { + Reply reply = {}; + output_.receive(&reply); + return reply.result; + } + + // Tell the test thread to pop a buffer from the queue. + // Call end_pop() to get the command's result, as well as the popped + // buffer if it is 0. + bool start_pop() { + input_.send(Request{Cmd::Pop, Buffer{}}); + return true; + } + + // Return the result of a previous start_pop() command. If result is + // 0, sets |*buffer| to the result buffer. + int end_pop(Buffer* buffer) { + Reply reply = {}; + output_.receive(&reply); + if (reply.result == 0) + *buffer = std::move(reply.buffer); + return reply.result; + } + + // Tell the test thread to close the queue from its side. + void do_close() { + input_.send(Request{Cmd::Close, Buffer{}}); + } + + // Tell the test thread to stop after completing its current command. + void stop() { + input_.send(Request{Cmd::Stop, Buffer{}}); + thread_.join(); + } + + private: + enum class Cmd { + Push, + Pop, + Close, + Stop, + }; + + struct Request { + Cmd cmd; + Buffer buffer; + }; + + struct Reply { + int result; + Buffer buffer; + }; + + void thread_main() { + while (true) { + Request r; + input_.receive(&r); + if (r.cmd == Cmd::Stop) + break; + std::unique_lock l(lock_); + Reply reply = {}; + bool sendReply = false; + switch (r.cmd) { + case Cmd::Push: + reply.result = queue_.push_locked(std::move(r.buffer), l); + sendReply = true; + break; + + case Cmd::Pop: + reply.result = queue_.pop_locked(&reply.buffer, l); + sendReply = true; + break; + + case Cmd::Close: + queue_.close_locked(); + break; + + default: + ; + } + if (sendReply) + output_.send(std::move(reply)); + } + } + + std::thread thread_; + std::mutex &lock_; + BufferQueue &queue_; + anbox::common::MessageChannel input_; + anbox::common::MessageChannel output_; +}; +} // namespace + +TEST(BufferQueue, PushLocked) { + std::mutex lock; + BufferQueue queue(2); + TestThread thread(lock, queue); + + ASSERT_TRUE(thread.start()); + ASSERT_TRUE(thread.start_pop()); + + std::unique_lock l(lock); + EXPECT_EQ(0, queue.push_locked(Buffer("Hello"), l)); + EXPECT_EQ(0, queue.push_locked(Buffer("World"), l)); + EXPECT_EQ(0, queue.push_locked(Buffer("Foo"), l)); + + thread.stop(); +} + +TEST(BufferQueue, PushLockedWithClosedQueue) { + std::mutex lock; + BufferQueue queue(2); + TestThread thread(lock, queue); + + ASSERT_TRUE(thread.start()); + + { + std::unique_lock l(lock); + EXPECT_EQ(0, queue.push_locked(Buffer("Hello"), l)); + // Closing the queue prevents pushing new items, but not + // pulling from the queue. + queue.close_locked(); + EXPECT_EQ(-EIO, queue.push_locked(Buffer("World"), l)); + } + + Buffer buffer; + ASSERT_TRUE(thread.start_pop()); + EXPECT_EQ(0, thread.end_pop(&buffer)); + EXPECT_STREQ("Hello", buffer.data()); + + thread.stop(); +} + +TEST(BufferQueue, PopLocked) { + std::mutex lock; + BufferQueue queue(2); + TestThread thread(lock, queue); + + ASSERT_TRUE(thread.start()); + ASSERT_TRUE(thread.start_push(Buffer("Hello World"))); + EXPECT_EQ(0, thread.end_push()); + + { + std::unique_lock l(lock); + Buffer buffer; + EXPECT_EQ(0, queue.pop_locked(&buffer, l)); + EXPECT_STREQ("Hello World", buffer.data()); + } + + thread.stop(); +} + +TEST(BufferQueue, PopLockedWithClosedQueue) { + std::mutex lock; + BufferQueue queue(2); + TestThread thread(lock, queue); + + ASSERT_TRUE(thread.start()); + ASSERT_TRUE(thread.start_push(Buffer("Hello World"))); + EXPECT_EQ(0, thread.end_push()); + + // Closing the queue shall not prevent pulling items from it. + // After that, -EIO shall be returned. + thread.do_close(); + + ASSERT_TRUE(thread.start_push(Buffer("Foo Bar"))); + EXPECT_EQ(-EIO, thread.end_push()); + + { + std::unique_lock l(lock); + Buffer buffer; + EXPECT_EQ(0, queue.pop_locked(&buffer, l)); + EXPECT_STREQ("Hello World", buffer.data()); + + EXPECT_EQ(-EIO, queue.pop_locked(&buffer, l)); + EXPECT_STREQ("Hello World", buffer.data()); + } + + thread.stop(); +} +} // namespace graphics +} // namespace anbox