1/* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <iostream> 18 19#include <gtest/gtest.h> 20#include <stdlib.h> 21 22#include "fifo/FifoBuffer.h" 23#include "fifo/FifoController.h" 24 25using android::fifo_frames_t; 26using android::FifoController; 27using android::FifoBuffer; 28using android::WrappingBuffer; 29 30//void foo() { 31TEST(test_fifi_controller, fifo_indices) { 32 // Values are arbitrary primes designed to trigger edge cases. 33 constexpr int capacity = 83; 34 constexpr int threshold = 47; 35 FifoController fifoController(capacity, threshold); 36 ASSERT_EQ(capacity, fifoController.getCapacity()); 37 ASSERT_EQ(threshold, fifoController.getThreshold()); 38 39 ASSERT_EQ(0, fifoController.getReadCounter()); 40 ASSERT_EQ(0, fifoController.getWriteCounter()); 41 ASSERT_EQ(0, fifoController.getFullFramesAvailable()); 42 ASSERT_EQ(threshold, fifoController.getEmptyFramesAvailable()); 43 44 // Pretend to write some data. 45 constexpr int advance1 = 23; 46 fifoController.advanceWriteIndex(advance1); 47 int advanced = advance1; 48 ASSERT_EQ(0, fifoController.getReadCounter()); 49 ASSERT_EQ(0, fifoController.getReadIndex()); 50 ASSERT_EQ(advanced, fifoController.getWriteCounter()); 51 ASSERT_EQ(advanced, fifoController.getWriteIndex()); 52 ASSERT_EQ(advanced, fifoController.getFullFramesAvailable()); 53 ASSERT_EQ(threshold - advanced, fifoController.getEmptyFramesAvailable()); 54 55 // Pretend to read the data. 56 fifoController.advanceReadIndex(advance1); 57 ASSERT_EQ(advanced, fifoController.getReadCounter()); 58 ASSERT_EQ(advanced, fifoController.getReadIndex()); 59 ASSERT_EQ(advanced, fifoController.getWriteCounter()); 60 ASSERT_EQ(advanced, fifoController.getWriteIndex()); 61 ASSERT_EQ(0, fifoController.getFullFramesAvailable()); 62 ASSERT_EQ(threshold, fifoController.getEmptyFramesAvailable()); 63 64 // Write past end of buffer. 65 constexpr int advance2 = 13 + capacity - advance1; 66 fifoController.advanceWriteIndex(advance2); 67 advanced += advance2; 68 ASSERT_EQ(advance1, fifoController.getReadCounter()); 69 ASSERT_EQ(advance1, fifoController.getReadIndex()); 70 ASSERT_EQ(advanced, fifoController.getWriteCounter()); 71 ASSERT_EQ(advanced - capacity, fifoController.getWriteIndex()); 72 ASSERT_EQ(advance2, fifoController.getFullFramesAvailable()); 73 ASSERT_EQ(threshold - advance2, fifoController.getEmptyFramesAvailable()); 74} 75 76// TODO consider using a template for other data types. 77class TestFifoBuffer { 78public: 79 explicit TestFifoBuffer(fifo_frames_t capacity, fifo_frames_t threshold = 0) 80 : mFifoBuffer(sizeof(int16_t), capacity) { 81 // For reading and writing. 82 mData = new int16_t[capacity]; 83 if (threshold <= 0) { 84 threshold = capacity; 85 } 86 mFifoBuffer.setThreshold(threshold); 87 mThreshold = threshold; 88 } 89 90 void checkMisc() { 91 ASSERT_EQ((int32_t)(2 * sizeof(int16_t)), mFifoBuffer.convertFramesToBytes(2)); 92 ASSERT_EQ(mThreshold, mFifoBuffer.getThreshold()); 93 } 94 95 // Verify that the available frames in each part add up correctly. 96 void checkWrappingBuffer() { 97 WrappingBuffer wrappingBuffer; 98 fifo_frames_t framesAvailable = 99 mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable(); 100 fifo_frames_t wrapAvailable = mFifoBuffer.getEmptyRoomAvailable(&wrappingBuffer); 101 EXPECT_EQ(framesAvailable, wrapAvailable); 102 fifo_frames_t bothAvailable = wrappingBuffer.numFrames[0] + wrappingBuffer.numFrames[1]; 103 EXPECT_EQ(framesAvailable, bothAvailable); 104 105 framesAvailable = 106 mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable(); 107 wrapAvailable = mFifoBuffer.getFullDataAvailable(&wrappingBuffer); 108 EXPECT_EQ(framesAvailable, wrapAvailable); 109 bothAvailable = wrappingBuffer.numFrames[0] + wrappingBuffer.numFrames[1]; 110 EXPECT_EQ(framesAvailable, bothAvailable); 111 } 112 113 // Write data but do not overflow. 114 void writeData(fifo_frames_t numFrames) { 115 fifo_frames_t framesAvailable = 116 mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable(); 117 fifo_frames_t framesToWrite = std::min(framesAvailable, numFrames); 118 for (int i = 0; i < framesToWrite; i++) { 119 mData[i] = mNextWriteIndex++; 120 } 121 fifo_frames_t actual = mFifoBuffer.write(mData, framesToWrite); 122 ASSERT_EQ(framesToWrite, actual); 123 } 124 125 // Read data but do not underflow. 126 void verifyData(fifo_frames_t numFrames) { 127 fifo_frames_t framesAvailable = 128 mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable(); 129 fifo_frames_t framesToRead = std::min(framesAvailable, numFrames); 130 fifo_frames_t actual = mFifoBuffer.read(mData, framesToRead); 131 ASSERT_EQ(framesToRead, actual); 132 for (int i = 0; i < framesToRead; i++) { 133 ASSERT_EQ(mNextVerifyIndex++, mData[i]); 134 } 135 } 136 137 // Wrap around the end of the buffer. 138 void checkWrappingWriteRead() { 139 constexpr int frames1 = 43; 140 constexpr int frames2 = 15; 141 142 writeData(frames1); 143 checkWrappingBuffer(); 144 verifyData(frames1); 145 checkWrappingBuffer(); 146 147 writeData(frames2); 148 checkWrappingBuffer(); 149 verifyData(frames2); 150 checkWrappingBuffer(); 151 } 152 153 // Write and Read a specific amount of data. 154 void checkWriteRead() { 155 const fifo_frames_t capacity = mFifoBuffer.getBufferCapacityInFrames(); 156 // Wrap around with the smaller region in the second half. 157 const int frames1 = capacity - 4; 158 const int frames2 = 7; // arbitrary, small 159 writeData(frames1); 160 verifyData(frames1); 161 writeData(frames2); 162 verifyData(frames2); 163 } 164 165 // Write and Read a specific amount of data. 166 void checkWriteReadSmallLarge() { 167 const fifo_frames_t capacity = mFifoBuffer.getBufferCapacityInFrames(); 168 // Wrap around with the larger region in the second half. 169 const int frames1 = capacity - 4; 170 const int frames2 = capacity - 9; // arbitrary, large 171 writeData(frames1); 172 verifyData(frames1); 173 writeData(frames2); 174 verifyData(frames2); 175 } 176 177 // Randomly read or write up to the maximum amount of data. 178 void checkRandomWriteRead() { 179 for (int i = 0; i < 20; i++) { 180 fifo_frames_t framesEmpty = 181 mFifoBuffer.getFifoControllerBase()->getEmptyFramesAvailable(); 182 fifo_frames_t numFrames = (fifo_frames_t)(drand48() * framesEmpty); 183 writeData(numFrames); 184 185 fifo_frames_t framesFull = 186 mFifoBuffer.getFifoControllerBase()->getFullFramesAvailable(); 187 numFrames = (fifo_frames_t)(drand48() * framesFull); 188 verifyData(numFrames); 189 } 190 } 191 192 FifoBuffer mFifoBuffer; 193 int16_t *mData; 194 fifo_frames_t mNextWriteIndex = 0; 195 fifo_frames_t mNextVerifyIndex = 0; 196 fifo_frames_t mThreshold; 197}; 198 199TEST(test_fifo_buffer, fifo_read_write) { 200 constexpr int capacity = 51; // arbitrary 201 TestFifoBuffer tester(capacity); 202 tester.checkMisc(); 203 tester.checkWriteRead(); 204} 205 206TEST(test_fifo_buffer, fifo_wrapping_read_write) { 207 constexpr int capacity = 59; // arbitrary, a little bigger this time 208 TestFifoBuffer tester(capacity); 209 tester.checkWrappingWriteRead(); 210} 211 212TEST(test_fifo_buffer, fifo_read_write_small_large) { 213 constexpr int capacity = 51; // arbitrary 214 TestFifoBuffer tester(capacity); 215 tester.checkWriteReadSmallLarge(); 216} 217 218TEST(test_fifo_buffer, fifo_random_read_write) { 219 constexpr int capacity = 51; // arbitrary 220 TestFifoBuffer tester(capacity); 221 tester.checkRandomWriteRead(); 222} 223 224TEST(test_fifo_buffer, fifo_random_threshold) { 225 constexpr int capacity = 67; // arbitrary 226 constexpr int threshold = 37; // arbitrary 227 TestFifoBuffer tester(capacity, threshold); 228 tester.checkRandomWriteRead(); 229} 230