244 lines
9.1 KiB
C++
244 lines
9.1 KiB
C++
|
|
#include "pch.h"
|
||
|
|
#include "MockWebMFileReader.h"
|
||
|
|
#include "MockVideoRenderer.h"
|
||
|
|
// Note: VideoPlayerControl integration testing would require WinUI3 mocking
|
||
|
|
// For now, this focuses on testing the integration patterns and dependency injection
|
||
|
|
|
||
|
|
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
|
||
|
|
using namespace Vav2PlayerUnitTests;
|
||
|
|
|
||
|
|
namespace Vav2PlayerUnitTests
|
||
|
|
{
|
||
|
|
TEST_CLASS(VideoPlayerControlTest)
|
||
|
|
{
|
||
|
|
public:
|
||
|
|
TEST_METHOD(DependencyInjection_MockComponents_ShouldWorkTogether)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockReader = std::make_unique<MockWebMFileReader>();
|
||
|
|
auto mockRenderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
|
||
|
|
MockWebMFileReader* readerPtr = mockReader.get();
|
||
|
|
MockVideoRenderer* rendererPtr = mockRenderer.get();
|
||
|
|
|
||
|
|
// Set up mock data
|
||
|
|
VideoMetadata metadata;
|
||
|
|
metadata.width = 1920;
|
||
|
|
metadata.height = 1080;
|
||
|
|
metadata.frame_rate = 30.0;
|
||
|
|
metadata.codec_type = VideoCodecType::AV1;
|
||
|
|
readerPtr->SetMockVideoMetadata(metadata);
|
||
|
|
|
||
|
|
// Act - Simulate VideoPlayerControl workflow
|
||
|
|
bool openResult = readerPtr->OpenFile("test_video.webm");
|
||
|
|
auto tracks = readerPtr->GetVideoTracks();
|
||
|
|
bool selectResult = readerPtr->SelectVideoTrack(tracks[0].track_number);
|
||
|
|
|
||
|
|
HRESULT initResult = rendererPtr->Initialize(metadata.width, metadata.height);
|
||
|
|
|
||
|
|
// Read and "render" first frame
|
||
|
|
VideoPacket packet;
|
||
|
|
bool readResult = readerPtr->ReadNextPacket(packet);
|
||
|
|
|
||
|
|
// Create mock video frame for rendering test
|
||
|
|
VideoFrame frame;
|
||
|
|
frame.width = metadata.width;
|
||
|
|
frame.height = metadata.height;
|
||
|
|
frame.format = PixelFormat::YUV420P;
|
||
|
|
frame.frame_index = 0;
|
||
|
|
|
||
|
|
bool renderResult = rendererPtr->TryRenderFrame(frame);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::IsTrue(openResult);
|
||
|
|
Assert::IsTrue(selectResult);
|
||
|
|
Assert::AreEqual(S_OK, initResult);
|
||
|
|
Assert::IsTrue(readResult);
|
||
|
|
Assert::IsTrue(renderResult);
|
||
|
|
|
||
|
|
// Verify call counts
|
||
|
|
Assert::AreEqual(1u, readerPtr->GetOpenFileCallCount());
|
||
|
|
Assert::AreEqual(1u, readerPtr->GetReadPacketCallCount());
|
||
|
|
Assert::AreEqual(1u, rendererPtr->GetInitializeCallCount());
|
||
|
|
Assert::AreEqual(1u, rendererPtr->GetTryRenderFrameCallCount());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(ErrorHandling_FileNotFound_ShouldPropagateError)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockReader = std::make_unique<MockWebMFileReader>();
|
||
|
|
mockReader->SetOpenFileResult(false);
|
||
|
|
|
||
|
|
// Act
|
||
|
|
bool result = mockReader->OpenFile("nonexistent.webm");
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::IsFalse(result);
|
||
|
|
Assert::AreEqual(WebMErrorCode::FileNotFound, mockReader->GetLastError());
|
||
|
|
Assert::IsFalse(mockReader->GetLastErrorString().empty());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(ErrorHandling_RendererInitializationFailure_ShouldBeHandled)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockRenderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
mockRenderer->SimulateInitializationFailure(true);
|
||
|
|
|
||
|
|
// Act
|
||
|
|
HRESULT result = mockRenderer->Initialize(1920, 1080);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::AreEqual(E_FAIL, result);
|
||
|
|
Assert::IsFalse(mockRenderer->IsInitialized());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(PlaybackSimulation_MultipleFrames_ShouldMaintainState)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockReader = std::make_unique<MockWebMFileReader>();
|
||
|
|
auto mockRenderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
|
||
|
|
mockReader->OpenFile("test.webm");
|
||
|
|
mockReader->SelectVideoTrack(1);
|
||
|
|
mockRenderer->Initialize(1920, 1080);
|
||
|
|
|
||
|
|
// Act - Simulate playing 10 frames
|
||
|
|
for (int i = 0; i < 10; ++i) {
|
||
|
|
VideoPacket packet;
|
||
|
|
bool readResult = mockReader->ReadNextPacket(packet);
|
||
|
|
|
||
|
|
if (readResult) {
|
||
|
|
// Create frame from packet (simplified)
|
||
|
|
VideoFrame frame;
|
||
|
|
frame.width = 1920;
|
||
|
|
frame.height = 1080;
|
||
|
|
frame.frame_index = packet.frame_index;
|
||
|
|
frame.timestamp_ns = static_cast<uint64_t>(packet.timestamp_seconds * 1000000000.0);
|
||
|
|
|
||
|
|
mockRenderer->TryRenderFrame(frame);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::AreEqual(10u, mockReader->GetReadPacketCallCount());
|
||
|
|
Assert::AreEqual(10u, mockRenderer->GetTryRenderFrameCallCount());
|
||
|
|
Assert::AreEqual(static_cast<uint64_t>(10u), mockReader->GetCurrentFrameIndex());
|
||
|
|
Assert::AreEqual(10u, mockRenderer->GetTotalRenderedFrames());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(SeekOperation_ShouldUpdateReaderState)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockReader = std::make_unique<MockWebMFileReader>();
|
||
|
|
mockReader->OpenFile("test.webm");
|
||
|
|
mockReader->SelectVideoTrack(1);
|
||
|
|
|
||
|
|
// Read some packets first
|
||
|
|
for (int i = 0; i < 5; ++i) {
|
||
|
|
VideoPacket packet;
|
||
|
|
mockReader->ReadNextPacket(packet);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Act - Seek to frame 50
|
||
|
|
bool seekResult = mockReader->SeekToFrame(50);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::IsTrue(seekResult);
|
||
|
|
Assert::AreEqual(50u, static_cast<uint32_t>(mockReader->GetCurrentFrameIndex()));
|
||
|
|
|
||
|
|
// Next packet should be frame 50
|
||
|
|
VideoPacket packet;
|
||
|
|
bool readResult = mockReader->ReadNextPacket(packet);
|
||
|
|
Assert::IsTrue(readResult);
|
||
|
|
Assert::AreEqual(50u, static_cast<uint32_t>(packet.frame_index));
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(AspectRatioHandling_ShouldUpdateRenderer)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockRenderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
mockRenderer->Initialize(1920, 1080);
|
||
|
|
|
||
|
|
// Act - Simulate container size changes (AspectFit scenario)
|
||
|
|
mockRenderer->UpdateContainerSize(1280, 720); // 16:9 container
|
||
|
|
mockRenderer->SetAspectFitMode(true);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::AreEqual(1280u, mockRenderer->GetContainerWidth());
|
||
|
|
Assert::AreEqual(720u, mockRenderer->GetContainerHeight());
|
||
|
|
Assert::IsTrue(mockRenderer->GetAspectFitMode());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(ResourceCleanup_ShouldReleaseResources)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockReader = std::make_unique<MockWebMFileReader>();
|
||
|
|
auto mockRenderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
|
||
|
|
mockReader->OpenFile("test.webm");
|
||
|
|
mockRenderer->Initialize(1920, 1080);
|
||
|
|
|
||
|
|
// Render some frames
|
||
|
|
for (int i = 0; i < 3; ++i) {
|
||
|
|
VideoFrame frame;
|
||
|
|
frame.width = 1920;
|
||
|
|
frame.height = 1080;
|
||
|
|
frame.frame_index = i;
|
||
|
|
mockRenderer->RenderVideoFrame(frame);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Act - Cleanup
|
||
|
|
mockReader->CloseFile();
|
||
|
|
mockRenderer->Shutdown();
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::IsFalse(mockReader->IsFileOpen());
|
||
|
|
Assert::IsFalse(mockRenderer->IsInitialized());
|
||
|
|
Assert::AreEqual(0u, mockRenderer->GetTotalRenderedFrames()); // Should be cleared
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(PerformanceMetrics_ShouldBeTracked)
|
||
|
|
{
|
||
|
|
// Arrange
|
||
|
|
auto mockRenderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
mockRenderer->Initialize(1920, 1080);
|
||
|
|
mockRenderer->SetRenderDelay(5); // 5ms per frame
|
||
|
|
|
||
|
|
// Act - Render frames with timing
|
||
|
|
auto start = std::chrono::high_resolution_clock::now();
|
||
|
|
|
||
|
|
for (int i = 0; i < 5; ++i) {
|
||
|
|
VideoFrame frame;
|
||
|
|
frame.width = 1920;
|
||
|
|
frame.height = 1080;
|
||
|
|
frame.frame_index = i;
|
||
|
|
mockRenderer->RenderVideoFrame(frame);
|
||
|
|
}
|
||
|
|
|
||
|
|
auto end = std::chrono::high_resolution_clock::now();
|
||
|
|
auto totalTime = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::IsTrue(totalTime.count() >= 25); // At least 25ms (5ms * 5 frames)
|
||
|
|
Assert::IsTrue(mockRenderer->GetTotalRenderTime() >= 25);
|
||
|
|
Assert::AreEqual(5u, mockRenderer->GetTotalRenderedFrames());
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_METHOD(InterfaceCompatibility_ShouldWorkWithBasePointers)
|
||
|
|
{
|
||
|
|
// Arrange - Test polymorphism through interfaces
|
||
|
|
std::unique_ptr<IWebMFileReader> reader = std::make_unique<MockWebMFileReader>();
|
||
|
|
std::unique_ptr<IVideoRenderer> renderer = std::make_unique<MockVideoRenderer>();
|
||
|
|
|
||
|
|
// Act - Use through interface pointers
|
||
|
|
bool openResult = reader->OpenFile("test.webm");
|
||
|
|
HRESULT initResult = renderer->Initialize(1920, 1080);
|
||
|
|
|
||
|
|
// Assert
|
||
|
|
Assert::IsTrue(openResult);
|
||
|
|
Assert::AreEqual(S_OK, initResult);
|
||
|
|
Assert::IsTrue(reader->IsFileOpen());
|
||
|
|
Assert::IsTrue(renderer->IsInitialized());
|
||
|
|
}
|
||
|
|
};
|
||
|
|
}
|