1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/basictypes.h"
6#include "base/bind.h"
7#include "base/memory/scoped_ptr.h"
8#include "chromecast/media/cma/ipc/media_memory_chunk.h"
9#include "chromecast/media/cma/ipc/media_message.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace chromecast {
13namespace media {
14
15namespace {
16
17class ExternalMemoryBlock
18    : public MediaMemoryChunk {
19 public:
20  ExternalMemoryBlock(void* data, size_t size)
21      : data_(data), size_(size) {}
22  virtual ~ExternalMemoryBlock() {}
23
24  // MediaMemoryChunk implementation.
25  virtual void* data() const OVERRIDE { return data_; }
26  virtual size_t size() const OVERRIDE { return size_; }
27  virtual bool valid() const OVERRIDE { return true; }
28
29 private:
30  void* const data_;
31  const size_t size_;
32};
33
34scoped_ptr<MediaMemoryChunk> DummyAllocator(
35    void* data, size_t size, size_t alloc_size) {
36  CHECK_LE(alloc_size, size);
37  return scoped_ptr<MediaMemoryChunk>(
38      new ExternalMemoryBlock(data, alloc_size));
39}
40
41}
42
43TEST(MediaMessageTest, WriteRead) {
44  int buffer_size = 1024;
45  scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
46  MediaMessage::MemoryAllocatorCB mem_alloc_cb(
47      base::Bind(&DummyAllocator, buffer.get(), buffer_size));
48  uint32 type = 0x1;
49  int msg_content_capacity = 512;
50
51  // Write a message.
52  int count = 64;
53  scoped_ptr<MediaMessage> msg1(
54      MediaMessage::CreateMessage(type, mem_alloc_cb, msg_content_capacity));
55  for (int k = 0; k < count; k++) {
56    int v1 = 2 * k + 1;
57    EXPECT_TRUE(msg1->WritePod(v1));
58    uint8 v2 = k;
59    EXPECT_TRUE(msg1->WritePod(v2));
60  }
61  EXPECT_EQ(msg1->content_size(), count * (sizeof(int) + sizeof(uint8)));
62
63  // Verify the integrity of the message.
64  scoped_ptr<MediaMessage> msg2(
65      MediaMessage::MapMessage(scoped_ptr<MediaMemoryChunk>(
66          new ExternalMemoryBlock(&buffer[0], buffer_size))));
67  for (int k = 0; k < count; k++) {
68    int v1;
69    int expected_v1 = 2 * k + 1;
70    EXPECT_TRUE(msg2->ReadPod(&v1));
71    EXPECT_EQ(v1, expected_v1);
72    uint8 v2;
73    uint8 expected_v2 = k;
74    EXPECT_TRUE(msg2->ReadPod(&v2));
75    EXPECT_EQ(v2, expected_v2);
76  }
77}
78
79TEST(MediaMessageTest, WriteOverflow) {
80  int buffer_size = 1024;
81  scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
82  MediaMessage::MemoryAllocatorCB mem_alloc_cb(
83      base::Bind(&DummyAllocator, buffer.get(), buffer_size));
84  uint32 type = 0x1;
85  int msg_content_capacity = 8;
86
87  scoped_ptr<MediaMessage> msg1(
88      MediaMessage::CreateMessage(type, mem_alloc_cb, msg_content_capacity));
89  uint32 v1 = 0;
90  uint8 v2 = 0;
91  EXPECT_TRUE(msg1->WritePod(v1));
92  EXPECT_TRUE(msg1->WritePod(v1));
93
94  EXPECT_FALSE(msg1->WritePod(v1));
95  EXPECT_FALSE(msg1->WritePod(v2));
96}
97
98TEST(MediaMessageTest, ReadOverflow) {
99  int buffer_size = 1024;
100  scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
101  MediaMessage::MemoryAllocatorCB mem_alloc_cb(
102      base::Bind(&DummyAllocator, buffer.get(), buffer_size));
103  uint32 type = 0x1;
104  int msg_content_capacity = 8;
105
106  scoped_ptr<MediaMessage> msg1(
107      MediaMessage::CreateMessage(type, mem_alloc_cb, msg_content_capacity));
108  uint32 v1 = 0xcd;
109  EXPECT_TRUE(msg1->WritePod(v1));
110  EXPECT_TRUE(msg1->WritePod(v1));
111
112  scoped_ptr<MediaMessage> msg2(
113      MediaMessage::MapMessage(scoped_ptr<MediaMemoryChunk>(
114          new ExternalMemoryBlock(&buffer[0], buffer_size))));
115  uint32 v2;
116  EXPECT_TRUE(msg2->ReadPod(&v2));
117  EXPECT_EQ(v2, v1);
118  EXPECT_TRUE(msg2->ReadPod(&v2));
119  EXPECT_EQ(v2, v1);
120  EXPECT_FALSE(msg2->ReadPod(&v2));
121}
122
123TEST(MediaMessageTest, DummyMessage) {
124  int buffer_size = 1024;
125  scoped_ptr<uint8[]> buffer(new uint8[buffer_size]);
126  MediaMessage::MemoryAllocatorCB mem_alloc_cb(
127      base::Bind(&DummyAllocator, buffer.get(), buffer_size));
128  uint32 type = 0x1;
129
130  // Create first a dummy message to estimate the content size.
131  scoped_ptr<MediaMessage> msg1(
132      MediaMessage::CreateDummyMessage(type));
133  uint32 v1 = 0xcd;
134  EXPECT_TRUE(msg1->WritePod(v1));
135  EXPECT_TRUE(msg1->WritePod(v1));
136
137  // Create the real message and write the actual content.
138  scoped_ptr<MediaMessage> msg2(
139      MediaMessage::CreateMessage(type, mem_alloc_cb, msg1->content_size()));
140  EXPECT_TRUE(msg2->WritePod(v1));
141  EXPECT_TRUE(msg2->WritePod(v1));
142  EXPECT_FALSE(msg2->WritePod(v1));
143}
144
145}  // namespace media
146}  // namespace chromecast
147