Skip to content

Commit

Permalink
Adding integration tests for default test app behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
SoylentGraham committed Jan 13, 2024
1 parent db8d63e commit 6ee2881
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 5 deletions.
24 changes: 20 additions & 4 deletions PopMp4.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
BF4366332B4AFA5F00009182 /* PopMp4.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF4366282B4AFA2E00009182 /* PopMp4.framework */; };
BF4366342B4AFA5F00009182 /* PopMp4.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BF4366282B4AFA2E00009182 /* PopMp4.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BF4366392B4AFCF500009182 /* PopMp4.h in Headers */ = {isa = PBXBuildFile; fileRef = BFC7E7BF26F0B68E0032E0DB /* PopMp4.h */; settings = {ATTRIBUTES = (Public, ); }; };
BFFF91902B52EE880096803A /* gtest-all.cc in Sources */ = {isa = PBXBuildFile; fileRef = BFFF918F2B52EE880096803A /* gtest-all.cc */; };
BFFF91922B52EF600096803A /* TestData in CopyFiles */ = {isa = PBXBuildFile; fileRef = BFFF91912B52EF3E0096803A /* TestData */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -54,12 +56,13 @@
};
BFC7E7AE26F0B6500032E0DB /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
buildActionMask = 12;
dstPath = "";
dstSubfolderSpec = 16;
files = (
BFFF91922B52EF600096803A /* TestData in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */

Expand All @@ -83,6 +86,8 @@
BFC7E7B026F0B6500032E0DB /* PopMp4_TestApp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PopMp4_TestApp; sourceTree = BUILT_PRODUCTS_DIR; };
BFC7E7BC26F0B67F0032E0DB /* PopMp4.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PopMp4.cpp; sourceTree = "<group>"; };
BFC7E7BF26F0B68E0032E0DB /* PopMp4.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PopMp4.h; sourceTree = "<group>"; };
BFFF918F2B52EE880096803A /* gtest-all.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "gtest-all.cc"; path = "googletest/googletest/src/gtest-all.cc"; sourceTree = "<group>"; };
BFFF91912B52EF3E0096803A /* TestData */ = {isa = PBXFileReference; lastKnownFileType = folder; path = TestData; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand All @@ -107,6 +112,7 @@
BF4366162B4AE80B00009182 /* Source_TestApp */ = {
isa = PBXGroup;
children = (
BFFF918E2B52EE7B0096803A /* googletest */,
BF4366172B4AE80B00009182 /* TestApp.cpp */,
);
path = Source_TestApp;
Expand Down Expand Up @@ -143,6 +149,7 @@
BFC7E7B226F0B6500032E0DB /* Source */,
BF4366182B4AE80B00009182 /* Source_Apple */,
BF4366162B4AE80B00009182 /* Source_TestApp */,
BFFF91912B52EF3E0096803A /* TestData */,
);
sourceTree = "<group>";
};
Expand All @@ -169,6 +176,14 @@
path = Source;
sourceTree = "<group>";
};
BFFF918E2B52EE7B0096803A /* googletest */ = {
isa = PBXGroup;
children = (
BFFF918F2B52EE880096803A /* gtest-all.cc */,
);
name = googletest;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXHeadersBuildPhase section */
Expand Down Expand Up @@ -307,6 +322,7 @@
buildActionMask = 2147483647;
files = (
BF43661E2B4AE82000009182 /* TestApp.cpp in Sources */,
BFFF91902B52EE880096803A /* gtest-all.cc in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
16 changes: 15 additions & 1 deletion Source_Apple/Macos_TestApp.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,18 @@ ENABLE_HARDENED_RUNTIME = NO // currently doesn't like signing of framework vs a
//ENABLE_APP_SANDBOX = YES
//CODE_SIGN_ENTITLEMENTS = Source_Macos/CRStreamer_Macos.entitlements

GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS) $(inherited) TARGET_MACOS

// https://github.com/google/googletest/issues/2195
// google test's global initialisers (from TEST()) throw in mac sandboxed mode (when launching from finder/open)
// because it cannot get a result from getcwd(). It feels like there would be more problems than this...
GOOGLETEST_PREPROCESSORS=GTEST_HAS_FILE_SYSTEM=0
GOOGLETEST_INCLUDE="Source_TestApp/googletest/googletest/include"
GOOGLETEST_SRCINCLUDE="Source_TestApp/googletest/googletest/"




HEADER_SEARCH_PATHS = $(HEADER_SEARCH_PATHS) $(GOOGLETEST_INCLUDE) $(GOOGLETEST_SRCINCLUDE)
GCC_PREPROCESSOR_DEFINITIONS = $(GCC_PREPROCESSOR_DEFINITIONS) $(inherited) TARGET_MACOS $(GOOGLETEST_PREPROCESSORS)


186 changes: 186 additions & 0 deletions Source_TestApp/TestApp.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
#include "PopMp4.h"
#include <iostream>
#include <sstream>
#include <chrono>
#include <thread>
#include <functional>

#include "gtest/gtest.h"
#define GTEST_TEST_NAME GetCurrentTestName()

std::string GetCurrentTestName()
{
// https://github.com/google/googletest/blob/main/docs/advanced.md#getting-the-current-tests-name
auto* const test_info = testing::UnitTest::GetInstance()->current_test_info();

// gr: todo: make sure this in the format that matches the filter
std::stringstream TestName;
TestName << test_info->test_suite_name() << "." << test_info->name();
return TestName.str();
}

/*
void InputThread(int Instance,std::istream& Input)
Expand Down Expand Up @@ -126,5 +142,175 @@ std::string GetVersion()
int main(int argc, const char * argv[])
{
std::cout << "PopMp4 version " << GetVersion() << std::endl;

// must be called prior to running any tests
testing::InitGoogleTest();

std::string_view GTestFilter = "";
//std::string_view GTestFilter = "**DecodeFile**";
if ( !GTestFilter.empty() )
{
using namespace testing;
GTEST_FLAG(filter) = std::string(GTestFilter);
}

static bool BreakOnTestError = false;
if ( BreakOnTestError )
GTEST_FLAG_SET(break_on_failure,true);

const auto ReturnCode = RUN_ALL_TESTS();

if ( ReturnCode != 0 )
return ReturnCode;

std::cerr << "Integration tests succeeded" << std::endl;
return 0;
}



class General_Tests : public testing::TestWithParam<bool>
{
protected:
};


TEST(General_Tests, PopMp4UnitTest )
{
//EXPECT_NO_THROW( PopJson::UnitTest() );
}


class DecodeResults_t
{
public:
int RootAtomCount = 0;

friend std::ostream& operator<<(std::ostream& os, const DecodeResults_t& Params)
{
os << "DecodeResults_t-->";
os << " RootAtomCount=" << Params.RootAtomCount;
return os;
}
};


class DecodeTestParams_t
{
public:
std::string Filename;
DecodeResults_t ExpectedResults;

friend std::ostream& operator<<(std::ostream& os, const DecodeTestParams_t& Params)
{
os << "DecodeTestParams_t-->";
os << " Filename=" << Params.Filename;
os << " ExpectedResults=" << Params.ExpectedResults;
return os;
}
};

class Decode_Tests : public testing::TestWithParam<DecodeTestParams_t>
{
};

auto DecodeTestValues = ::testing::Values
(
DecodeTestParams_t{.Filename="TestData/Test.mp4", .ExpectedResults{.RootAtomCount=1} }
);

INSTANTIATE_TEST_SUITE_P( Decode_Tests, Decode_Tests, DecodeTestValues );



std::thread RunThreadSafely(std::function<void()> Functor,std::string& Error,std::mutex& ErrorLock)
{
auto RunAndCatch = [=,&Error,&ErrorLock]()
{
try
{
Functor();
}
catch(std::exception& e)
{
std::lock_guard Lock(ErrorLock);
Error = e.what();
}
};
return std::thread( RunAndCatch );
}



TEST_P(Decode_Tests,DecodeAtomTree)
{
auto Params = GetParam();

auto Decoder = PopMp4_CreateDecoder();

auto TestStartTime = std::chrono::system_clock::now();
auto TestMaxDuration = std::chrono::seconds(20);

std::mutex OutputLock;
std::string Error;
bool FinishedDecode = false;

auto ThrowIfTimeout = [&]()
{
auto ElapsedSecs = std::chrono::duration_cast<std::chrono::seconds>( std::chrono::system_clock::now() - TestStartTime );
if ( ElapsedSecs.count() > TestMaxDuration.count() )
throw std::runtime_error("Test timedout");
};
auto IsStillRunning = [&]()
{
try
{
ThrowIfTimeout();
std::scoped_lock Lock(OutputLock);
if ( FinishedDecode )
return false;
if ( !Error.empty() )
return false;
return true;
}
catch(...)
{
return false;
}
};


// monitor state
auto ReadStateThread = [&]()
{
std::vector<char> JsonBuffer( 1024 * 1024 * 1 );
while ( IsStillRunning() )
{
ThrowIfTimeout();

PopMp4_GetDecoderState( Decoder, JsonBuffer.data(), JsonBuffer.size() );
// parse
throw std::runtime_error("todo: parse state json");
}
};
auto ReadThread = RunThreadSafely( ReadStateThread, Error, OutputLock );

// stream data into decoder
auto OnReadData = [&](std::span<uint8_t> Data,bool Eof)
{
PopMp4_PushMp4Data( Decoder, Data.data(), Data.size(), Eof );
};

while ( IsStillRunning() )
{
std::cerr << GTEST_TEST_NAME << " waiting to finish..." << std::endl;
std::this_thread::sleep_for( std::chrono::seconds(1) );
}

if ( ReadThread.joinable() )
ReadThread.join();

if ( !Error.empty() )
FAIL() << Error;
//auto Image = DecodeFileFirstFrame( Params.Filename, Params.DecoderName );
}

0 comments on commit 6ee2881

Please sign in to comment.