Chromium Code Reviews| Index: media/gpu/video_decode_accelerator_unittest.cc |
| diff --git a/media/gpu/video_decode_accelerator_unittest.cc b/media/gpu/video_decode_accelerator_unittest.cc |
| index ed295a15010ef587332d2e6d5a0879537fab00d7..9ea874a5f016f07cf96018bb1fc34adb1efc1fe3 100644 |
| --- a/media/gpu/video_decode_accelerator_unittest.cc |
| +++ b/media/gpu/video_decode_accelerator_unittest.cc |
| @@ -206,15 +206,15 @@ void ReadGoldenThumbnailMD5s(const TestVideoFile* video_file, |
| if (md5_string.at(0) == '#') |
| continue; |
| - LOG_ASSERT(static_cast<int>(md5_string.length()) == kMD5StringLength) |
| - << md5_string; |
| + LOG_IF(WARNING, static_cast<int>(md5_string.length()) != kMD5StringLength) |
| + << "MD5 length error: " << md5_string; |
| bool hex_only = std::count_if(md5_string.begin(), md5_string.end(), |
| isxdigit) == kMD5StringLength; |
| - LOG_ASSERT(hex_only) << md5_string; |
| + LOG_IF(WARNING, !hex_only) << "MD5 includes non-hex char: " << md5_string; |
| } |
| - LOG_ASSERT(md5_strings->size() >= 1U) << " MD5 checksum file (" |
| - << filepath.MaybeAsASCII() |
| - << ") missing or empty."; |
| + LOG_IF(ERROR, md5_strings->size() < 1U) << " MD5 checksum file (" |
|
Owen Lin
2016/12/27 07:32:44
== 0
Why this one is error and others are just war
johnylin1
2016/12/27 14:02:06
My opinion is "missing file" will definitely make
wuchengli
2017/01/03 09:10:11
+1. Use LOG_IF(ERROR, for consistency because it's
johnylin1
2017/01/04 15:34:36
Done.
|
| + << filepath.MaybeAsASCII() |
| + << ") missing or empty."; |
| } |
| // State of the GLRenderingVDAClient below. Order matters here as the test |
| @@ -1280,20 +1280,53 @@ void VideoDecodeAcceleratorTest::OutputLogFile( |
| class VideoDecodeAcceleratorParamTest |
| : public VideoDecodeAcceleratorTest, |
| public ::testing::WithParamInterface< |
| - std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> {}; |
| + std::tuple<int, int, int, ResetPoint, ClientState, bool, bool>> { |
| + protected: |
| + using NotesVector = |
| + std::vector<std::unique_ptr<ClientStateNotification<ClientState>>>; |
| + using ClientsVector = std::vector<std::unique_ptr<GLRenderingVDAClient>>; |
| + |
| + // Delete all GLRenderingClient objects in their own thread. |
| + void DeleteClientsAndNotes(ClientsVector clients, NotesVector notes); |
| +}; |
| + |
| +void VideoDecodeAcceleratorParamTest::DeleteClientsAndNotes( |
|
wuchengli
2017/01/03 09:10:12
This can be renamed to VideoDecodeAcceleratorParam
johnylin1
2017/01/04 15:34:36
Sounds great. I override TearDown() in VideoDecode
|
| + ClientsVector clients, |
| + NotesVector notes) { |
| + std::unique_ptr<ClientsVector> clients2(new ClientsVector); |
| + clients2->swap(clients); |
| + std::unique_ptr<NotesVector> notes2(new NotesVector); |
| + notes2->swap(notes); |
| + |
| + // |clients| must be deleted first because |clients| use |notes2|. |
| + g_env->GetRenderingTaskRunner()->PostTask( |
| + FROM_HERE, base::Bind(&Delete<ClientsVector>, base::Passed(&clients2))); |
| + |
| + g_env->GetRenderingTaskRunner()->PostTask( |
| + FROM_HERE, base::Bind(&Delete<NotesVector>, base::Passed(¬es2))); |
| + |
| + WaitUntilIdle(); |
| +} |
| // Wait for |note| to report a state and if it's not |expected_state| then |
| -// assert |client| has deleted its decoder. |
| +// expect |client| has deleted its decoder and set terminate_ealy. |
| static void AssertWaitForStateOrDeleted( |
| ClientStateNotification<ClientState>* note, |
| GLRenderingVDAClient* client, |
| + bool* terminate_early, |
| ClientState expected_state) { |
| + // If terminate_early is true it means something is already wrong of decoder, |
| + // we should bypass all latter state checks. |
| + if (*terminate_early) |
| + return; |
| ClientState state = note->Wait(); |
| if (state == expected_state) |
| return; |
| - ASSERT_TRUE(client->decoder_deleted()) |
| - << "Decoder not deleted but Wait() returned " << state |
| - << ", instead of " << expected_state; |
| + if (!client->decoder_deleted()) { |
| + LOG(ERROR) << "Decoder not deleted but Wait() returned " << state |
| + << ", instead of " << expected_state; |
| + *terminate_early = true; |
| + } |
| } |
| // We assert a minimal number of concurrent decoders we expect to succeed. |
| @@ -1324,9 +1357,6 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
| // Suppress GL rendering for all tests when the "--rendering_fps" is 0. |
| const bool suppress_rendering = g_rendering_fps == 0; |
| - using NotesVector = |
| - std::vector<std::unique_ptr<ClientStateNotification<ClientState>>>; |
| - using ClientsVector = std::vector<std::unique_ptr<GLRenderingVDAClient>>; |
| NotesVector notes(num_concurrent_decoders); |
| ClientsVector clients(num_concurrent_decoders); |
| @@ -1380,42 +1410,60 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
| // Then wait for all the decodes to finish. |
| // Only check performance & correctness later if we play through only once. |
| bool skip_performance_and_correctness_checks = num_play_throughs > 1; |
| + bool terminate_early = false; |
|
Owen Lin
2016/12/27 07:32:44
Instead, can we have a helper function which retur
johnylin1
2017/01/04 15:34:36
This is no longer needed since we gonna delete cli
|
| for (size_t i = 0; i < num_concurrent_decoders; ++i) { |
| ClientStateNotification<ClientState>* note = notes[i].get(); |
| ClientState state = note->Wait(); |
| if (state != CS_INITIALIZED) { |
| skip_performance_and_correctness_checks = true; |
| // We expect initialization to fail only when more than the supported |
| - // number of decoders is instantiated. Assert here that something else |
| - // didn't trigger failure. |
| - ASSERT_GT(num_concurrent_decoders, |
| - static_cast<size_t>(kMinSupportedNumConcurrentDecoders)); |
| + // number of decoders is instantiated. Break the loop and then terminate |
| + // test gracefully that something else didn't trigger failure. Do not use |
| + // assertion otherwise clients won't be deleted in the correct thread. |
| + if (num_concurrent_decoders <= |
| + static_cast<size_t>(kMinSupportedNumConcurrentDecoders)) { |
| + LOG(ERROR) << "Initialization failed while the number of decoders " |
| + << "is still supportable. num_concurrent_decoders = " |
| + << num_concurrent_decoders; |
| + terminate_early = true; |
| + break; |
| + } |
| continue; |
| } |
| - ASSERT_EQ(state, CS_INITIALIZED); |
| for (int n = 0; n < num_play_throughs; ++n) { |
| // For play-throughs other than the first, we expect initialization to |
| // succeed unconditionally. |
| if (n > 0) { |
| ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
| - note, clients[i].get(), CS_INITIALIZED)); |
| + note, clients[i].get(), &terminate_early, CS_INITIALIZED)); |
| } |
| // InitializeDone kicks off decoding inside the client, so we just need to |
| // wait for Flush. |
| - ASSERT_NO_FATAL_FAILURE( |
| - AssertWaitForStateOrDeleted(note, clients[i].get(), CS_FLUSHING)); |
| - ASSERT_NO_FATAL_FAILURE( |
| - AssertWaitForStateOrDeleted(note, clients[i].get(), CS_FLUSHED)); |
| + ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
| + note, clients[i].get(), &terminate_early, CS_FLUSHING)); |
| + ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
| + note, clients[i].get(), &terminate_early, CS_FLUSHED)); |
| // FlushDone requests Reset(). |
| - ASSERT_NO_FATAL_FAILURE( |
| - AssertWaitForStateOrDeleted(note, clients[i].get(), CS_RESETTING)); |
| + ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
| + note, clients[i].get(), &terminate_early, CS_RESETTING)); |
| } |
| - ASSERT_NO_FATAL_FAILURE( |
| - AssertWaitForStateOrDeleted(note, clients[i].get(), CS_RESET)); |
| + ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
| + note, clients[i].get(), &terminate_early, CS_RESET)); |
| // ResetDone requests Destroy(). |
| - ASSERT_NO_FATAL_FAILURE( |
| - AssertWaitForStateOrDeleted(note, clients[i].get(), CS_DESTROYED)); |
| + ASSERT_NO_FATAL_FAILURE(AssertWaitForStateOrDeleted( |
| + note, clients[i].get(), &terminate_early, CS_DESTROYED)); |
| + // Break the loop and terminate test gracefully if there is already |
| + // something wrong. |
| + if (terminate_early) |
| + break; |
| } |
| + // There is already something wrong and should delete clients and then stop |
| + // testing. |
| + if (terminate_early) { |
| + DeleteClientsAndNotes(std::move(clients), std::move(notes)); |
|
Owen Lin
2016/12/27 07:32:44
To me, it looks like the main issue here is to cal
johnylin1
2016/12/30 12:38:37
I got another idea is to delete clients and notes
johnylin1
2017/01/04 15:34:36
Override TearDown() is even better and also makes
|
| + } |
| + ASSERT_FALSE(terminate_early) << "Test is terminated due to failure above."; |
| + |
| // Finally assert that decoding went as expected. |
| for (size_t i = 0; |
| i < num_concurrent_decoders && !skip_performance_and_correctness_checks; |
| @@ -1485,9 +1533,9 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
| filepath = filepath.AddExtension(FILE_PATH_LITERAL(".png")); |
| int num_bytes = base::WriteFile( |
| filepath, reinterpret_cast<char*>(&png[0]), png.size()); |
| - ASSERT_EQ(num_bytes, static_cast<int>(png.size())); |
| + EXPECT_EQ(num_bytes, static_cast<int>(png.size())); |
| } |
| - ASSERT_NE(match, golden_md5s.end()); |
| + EXPECT_NE(match, golden_md5s.end()); |
| EXPECT_EQ(alpha_solid, true) << "RGBA frame had incorrect alpha"; |
| } |
| @@ -1503,19 +1551,7 @@ TEST_P(VideoDecodeAcceleratorParamTest, TestSimpleDecode) { |
| } |
| } |
| - std::unique_ptr<ClientsVector> clients2(new ClientsVector); |
| - clients2->swap(clients); |
| - std::unique_ptr<NotesVector> notes2(new NotesVector); |
| - notes2->swap(notes); |
| - |
| - // |clients| must be deleted first because |clients| use |notes2|. |
| - g_env->GetRenderingTaskRunner()->PostTask( |
| - FROM_HERE, base::Bind(&Delete<ClientsVector>, base::Passed(&clients2))); |
| - |
| - g_env->GetRenderingTaskRunner()->PostTask( |
| - FROM_HERE, base::Bind(&Delete<NotesVector>, base::Passed(¬es2))); |
| - |
| - WaitUntilIdle(); |
| + DeleteClientsAndNotes(std::move(clients), std::move(notes)); |
| }; |
| // Test that replay after EOS works fine. |