We decide we want to first ensure that the code properly calculates totalSeconds, a value sent to the descriptor. (We might not need to add this test if we’re not going to make changes to writeSnippet. The test exists here to demonstrate a specific technique.)
wav/14/WavReaderTest.cpp | |
| TEST_GROUP(WavReader_WriteSnippet) { |
| WavReader reader{"",""}; |
| istringstream input{""}; |
| FormatSubchunk formatSubchunk; |
| ostringstream output; |
| DataChunk dataChunk; |
| char* data; |
| uint32_t TwoBytesWorthOfBits{2 * 8}; |
| |
| void setup() override { |
| data = new char[4]; |
| } |
| |
| void teardown() override { |
| delete[] data; |
| } |
| }; |
| |
| TEST(WavReader_WriteSnippet, UpdatesTotalSeconds) { |
| dataChunk.length = 8; |
| formatSubchunk.bitsPerSample = TwoBytesWorthOfBits; |
| formatSubchunk.samplesPerSecond = 1; |
| |
| reader.writeSnippet("any", input, output, formatSubchunk, dataChunk, data); |
| |
| CHECK_EQUAL(8 / 2 / 1, reader.totalSeconds); |
| } |
We initialize a fair number of things in the test. Since none of them is relevant to the test’s expected result, we bury our initialization code in the WavReader_WriteSnippet test group (fixture) definition. We also move the struct definitions from WavReader.cpp into WavReader.h so that the test can access them (not shown).
Wait! How in the world are we verifying the value of totalSeconds, given that it was defined locally to writeSnippet? Simple: totalSeconds is now a public member variable!
wav/14/WavReader.h | |
| public: |
| // ... |
| uint32_t totalSeconds; |
wav/14/WavReader.cpp | |
| void WavReader::writeSnippet( |
| const string& name, istream& file, ostream& out, |
| FormatSubchunk& formatSubchunk, |
| DataChunk& dataChunk, |
| char* data |
| ) { |
| uint32_t secondsDesired{10}; |
| if (formatSubchunk.bitsPerSample == 0) formatSubchunk.bitsPerSample = 8; |
| uint32_t bytesPerSample{formatSubchunk.bitsPerSample / uint32_t{8}}; |
| |
| uint32_t samplesToWrite{secondsDesired * formatSubchunk.samplesPerSecond}; |
| uint32_t totalSamples{dataChunk.length / bytesPerSample}; |
| |
| samplesToWrite = min(samplesToWrite, totalSamples); |
| |
* | totalSeconds = totalSamples / formatSubchunk.samplesPerSecond; |
| |
| rLog(channel, "total seconds %u ", totalSeconds); |
| // ... |
| } |
Our test spies on the otherwise-hidden totalSeconds. Mother of all violations! Chill. Wrestling with a legacy codebase under control sometimes requires getting a little dirty. Remind yourself that it’s dirtier still to make changes and not know if you broke something.
Besides, we have a better way that will work for our case.
18.227.190.211