1// Copyright 2013 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 "media/midi/midi_message_queue.h"
6
7#include "testing/gtest/include/gtest/gtest.h"
8
9namespace media {
10namespace {
11
12const uint8 kGMOn[] = { 0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7 };
13const uint8 kGSOn[] = {
14  0xf0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x00, 0x7f, 0x00, 0x41, 0xf7,
15};
16const uint8 kNoteOn[] = { 0x90, 0x3c, 0x7f };
17const uint8 kNoteOnWithRunningStatus[] = {
18  0x90, 0x3c, 0x7f, 0x3c, 0x7f, 0x3c, 0x7f,
19};
20const uint8 kChannelPressure[] = { 0xd0, 0x01 };
21const uint8 kChannelPressureWithRunningStatus[] = {
22  0xd0, 0x01, 0x01, 0x01,
23};
24const uint8 kTimingClock[] = { 0xf8 };
25const uint8 kBrokenData1[] = { 0x90 };
26const uint8 kBrokenData2[] = { 0xf7 };
27const uint8 kBrokenData3[] = { 0xf2, 0x00 };
28const uint8 kDataByte0[] = { 0x00 };
29
30template <typename T, size_t N>
31void Add(MidiMessageQueue* queue, const T(&array)[N]) {
32  queue->Add(array, N);
33}
34
35template <typename T, size_t N>
36::testing::AssertionResult ExpectEqualSequence(
37    const char* expr1, const char* expr2,
38    const T(&expected)[N], const std::vector<T>& actual) {
39  if (actual.size() != N) {
40    return ::testing::AssertionFailure()
41        << "expected: " << ::testing::PrintToString(expected)
42        << ", actual: " << ::testing::PrintToString(actual);
43  }
44  for (size_t i = 0; i < N; ++i) {
45    if (expected[i] != actual[i]) {
46      return ::testing::AssertionFailure()
47          << "expected: " << ::testing::PrintToString(expected)
48          << ", actual: " << ::testing::PrintToString(actual);
49    }
50  }
51  return ::testing::AssertionSuccess();
52}
53
54#define EXPECT_MESSAGE(expected, actual)  \
55  EXPECT_PRED_FORMAT2(ExpectEqualSequence, expected, actual)
56
57TEST(MidiMessageQueueTest, EmptyData) {
58  MidiMessageQueue queue(false);
59  std::vector<uint8> message;
60  queue.Get(&message);
61  EXPECT_TRUE(message.empty());
62}
63
64TEST(MidiMessageQueueTest, RunningStatusDisabled) {
65  MidiMessageQueue queue(false);
66  Add(&queue, kGMOn);
67  Add(&queue, kBrokenData1);
68  Add(&queue, kNoteOnWithRunningStatus);
69  Add(&queue, kBrokenData2);
70  Add(&queue, kChannelPressureWithRunningStatus);
71  Add(&queue, kBrokenData3);
72  Add(&queue, kNoteOn);
73  Add(&queue, kBrokenData1);
74  Add(&queue, kGSOn);
75  Add(&queue, kBrokenData2);
76  Add(&queue, kTimingClock);
77  Add(&queue, kBrokenData3);
78
79  std::vector<uint8> message;
80  queue.Get(&message);
81  EXPECT_MESSAGE(kGMOn, message);
82  queue.Get(&message);
83  EXPECT_MESSAGE(kNoteOn, message) << "Running status should be ignored";
84  queue.Get(&message);
85  EXPECT_MESSAGE(kChannelPressure, message)
86      << "Running status should be ignored";
87  queue.Get(&message);
88  EXPECT_MESSAGE(kNoteOn, message);
89  queue.Get(&message);
90  EXPECT_MESSAGE(kGSOn, message);
91  queue.Get(&message);
92  EXPECT_MESSAGE(kTimingClock, message);
93  queue.Get(&message);
94  EXPECT_TRUE(message.empty());
95}
96
97TEST(MidiMessageQueueTest, RunningStatusEnabled) {
98  MidiMessageQueue queue(true);
99  Add(&queue, kGMOn);
100  Add(&queue, kBrokenData1);
101  Add(&queue, kNoteOnWithRunningStatus);
102  Add(&queue, kBrokenData2);
103  Add(&queue, kChannelPressureWithRunningStatus);
104  Add(&queue, kBrokenData3);
105  Add(&queue, kNoteOn);
106  Add(&queue, kBrokenData1);
107  Add(&queue, kGSOn);
108  Add(&queue, kBrokenData2);
109  Add(&queue, kTimingClock);
110  Add(&queue, kDataByte0);
111
112  std::vector<uint8> message;
113  queue.Get(&message);
114  EXPECT_MESSAGE(kGMOn, message);
115  queue.Get(&message);
116  EXPECT_MESSAGE(kNoteOn, message);
117  queue.Get(&message);
118  EXPECT_MESSAGE(kNoteOn, message)
119      << "Running status should be converted into a canonical MIDI message";
120  queue.Get(&message);
121  EXPECT_MESSAGE(kNoteOn, message)
122      << "Running status should be converted into a canonical MIDI message";
123  queue.Get(&message);
124  EXPECT_MESSAGE(kChannelPressure, message);
125  queue.Get(&message);
126  EXPECT_MESSAGE(kChannelPressure, message)
127      << "Running status should be converted into a canonical MIDI message";
128  queue.Get(&message);
129  EXPECT_MESSAGE(kChannelPressure, message)
130      << "Running status should be converted into a canonical MIDI message";
131  queue.Get(&message);
132  EXPECT_MESSAGE(kNoteOn, message);
133  queue.Get(&message);
134  EXPECT_MESSAGE(kGSOn, message);
135  queue.Get(&message);
136  EXPECT_MESSAGE(kTimingClock, message);
137  queue.Get(&message);
138  EXPECT_TRUE(message.empty())
139      << "Running status must not be applied to real time messages";
140}
141
142TEST(MidiMessageQueueTest, RunningStatusEnabledWithRealTimeEvent) {
143  MidiMessageQueue queue(true);
144  const uint8 kNoteOnWithRunningStatusWithkTimingClock[] = {
145    0x90, 0xf8, 0x3c, 0xf8, 0x7f, 0xf8, 0x3c, 0xf8, 0x7f, 0xf8, 0x3c, 0xf8,
146    0x7f,
147  };
148  Add(&queue, kNoteOnWithRunningStatusWithkTimingClock);
149  std::vector<uint8> message;
150  queue.Get(&message);
151  EXPECT_MESSAGE(kTimingClock, message);
152  queue.Get(&message);
153  EXPECT_MESSAGE(kTimingClock, message);
154  queue.Get(&message);
155  EXPECT_MESSAGE(kNoteOn, message);
156  queue.Get(&message);
157  EXPECT_MESSAGE(kTimingClock, message);
158  queue.Get(&message);
159  EXPECT_MESSAGE(kTimingClock, message);
160  queue.Get(&message);
161  EXPECT_MESSAGE(kNoteOn, message);
162  queue.Get(&message);
163  EXPECT_MESSAGE(kTimingClock, message);
164  queue.Get(&message);
165  EXPECT_MESSAGE(kTimingClock, message);
166  queue.Get(&message);
167  EXPECT_MESSAGE(kNoteOn, message);
168  queue.Get(&message);
169  EXPECT_TRUE(message.empty());
170}
171
172}  // namespace
173}  // namespace media
174