@@ -278,8 +278,17 @@ TEST(TaskTest, GetDynamicTypeReturnsCorrectEnum) {
278278}
279279
280280TEST (TaskTest, DestructorTerminatesIfWrongOrder) {
281- DummyTask task;
282- EXPECT_THROW (task.Run (), std::runtime_error);
281+ {
282+ DummyTask task;
283+ EXPECT_THROW (task.Run (), std::runtime_error);
284+ }
285+
286+ // Create a new task to complete the lifecycle properly
287+ DummyTask task2;
288+ task2.Validation ();
289+ task2.PreProcessing ();
290+ task2.Run ();
291+ task2.PostProcessing ();
283292}
284293
285294namespace my {
@@ -351,6 +360,249 @@ TEST(PerfTest, GetStringParamNameTest) {
351360 EXPECT_EQ (GetStringParamName (PerfResults::kNone ), " none" );
352361}
353362
363+ TEST (PerfTest, DefaultTimerReturnsNegativeOne) {
364+ EXPECT_EQ (DefaultTimer (), -1.0 );
365+ }
366+
367+ TEST (PerfTest, PerfAttrDefaultValues) {
368+ PerfAttr attr;
369+ EXPECT_EQ (attr.num_running , 5U );
370+ EXPECT_EQ (attr.current_timer (), -1.0 );
371+ }
372+
373+ TEST (PerfTest, PerfResultsDefaultValues) {
374+ PerfResults results;
375+ EXPECT_EQ (results.time_sec , 0.0 );
376+ EXPECT_EQ (results.type_of_running , PerfResults::kNone );
377+ EXPECT_EQ (PerfResults::kMaxTime , 10.0 );
378+ }
379+
380+ TEST (PerfTest, PerfResultsEnumValues) {
381+ EXPECT_EQ (static_cast <uint8_t >(PerfResults::kPipeline ), 0 );
382+ EXPECT_EQ (static_cast <uint8_t >(PerfResults::kTaskRun ), 1 );
383+ EXPECT_EQ (static_cast <uint8_t >(PerfResults::kNone ), 2 );
384+ }
385+
386+ TEST (PerfTest, PerfConstructorSetsTaskState) {
387+ auto task_ptr = std::make_shared<DummyTask>();
388+ Perf<int , int > perf (task_ptr);
389+
390+ EXPECT_EQ (task_ptr->GetStateOfTesting (), ppc::task::StateOfTesting::kPerf );
391+
392+ // Complete the task lifecycle to avoid destructor issues
393+ task_ptr->Validation ();
394+ task_ptr->PreProcessing ();
395+ task_ptr->Run ();
396+ task_ptr->PostProcessing ();
397+ }
398+
399+ TEST (PerfTest, GetPerfResultsReturnsCorrectResults) {
400+ auto task_ptr = std::make_shared<DummyTask>();
401+ Perf<int , int > perf (task_ptr);
402+
403+ // Initially should be default values
404+ auto initial_results = perf.GetPerfResults ();
405+ EXPECT_EQ (initial_results.time_sec , 0.0 );
406+ EXPECT_EQ (initial_results.type_of_running , PerfResults::kNone );
407+
408+ PerfAttr attr;
409+ double time = 0.0 ;
410+ attr.current_timer = [&time]() {
411+ double t = time;
412+ time += 0.5 ;
413+ return t;
414+ };
415+
416+ perf.PipelineRun (attr);
417+ auto pipeline_results = perf.GetPerfResults ();
418+ EXPECT_EQ (pipeline_results.type_of_running , PerfResults::kPipeline );
419+ EXPECT_GT (pipeline_results.time_sec , 0.0 );
420+
421+ perf.TaskRun (attr);
422+ auto taskrun_results = perf.GetPerfResults ();
423+ EXPECT_EQ (taskrun_results.type_of_running , PerfResults::kTaskRun );
424+ EXPECT_GT (taskrun_results.time_sec , 0.0 );
425+ }
426+
427+ TEST (PerfTest, CommonRunCalculatesAverageTime) {
428+ auto task_ptr = std::make_shared<DummyTask>();
429+ Perf<int , int > perf (task_ptr);
430+
431+ PerfAttr attr;
432+ int call_count = 0 ;
433+ attr.num_running = 3 ;
434+ attr.current_timer = [&call_count]() {
435+ if (call_count == 0 ) {
436+ call_count++;
437+ return 0.0 ; // Start time
438+ } else {
439+ return 3.0 ; // End time after 3 runs
440+ }
441+ };
442+
443+ perf.PipelineRun (attr);
444+ auto results = perf.GetPerfResults ();
445+
446+ // Total time should be 3 seconds, average should be 1 second (3.0 - 0.0) / 3
447+ EXPECT_DOUBLE_EQ (results.time_sec , 1.0 );
448+ }
449+
450+ TEST (PerfTest, PrintPerfStatisticPipelineOutput) {
451+ auto task_ptr = std::make_shared<DummyTask>();
452+ Perf<int , int > perf (task_ptr);
453+
454+ PerfAttr attr;
455+ double time = 0.0 ;
456+ attr.current_timer = [&time]() {
457+ double t = time;
458+ time += 0.1 ;
459+ return t;
460+ };
461+
462+ perf.PipelineRun (attr);
463+
464+ testing::internal::CaptureStdout ();
465+ perf.PrintPerfStatistic (" test_pipeline" );
466+ std::string output = testing::internal::GetCapturedStdout ();
467+
468+ EXPECT_NE (output.find (" test_pipeline:pipeline:" ), std::string::npos);
469+ EXPECT_NE (output.find (" 0.0200000000" ), std::string::npos); // 0.1/5 = 0.02
470+ }
471+
472+ TEST (PerfTest, PrintPerfStatisticTaskRunOutput) {
473+ auto task_ptr = std::make_shared<DummyTask>();
474+ Perf<int , int > perf (task_ptr);
475+
476+ PerfAttr attr;
477+ double time = 0.0 ;
478+ attr.current_timer = [&time]() {
479+ double t = time;
480+ time += 0.25 ;
481+ return t;
482+ };
483+
484+ perf.TaskRun (attr);
485+
486+ testing::internal::CaptureStdout ();
487+ perf.PrintPerfStatistic (" test_taskrun" );
488+ std::string output = testing::internal::GetCapturedStdout ();
489+
490+ EXPECT_NE (output.find (" test_taskrun:task_run:" ), std::string::npos);
491+ }
492+
493+ TEST (PerfTest, PrintPerfStatisticThrowsOnExceedingMaxTime) {
494+ auto task_ptr = std::make_shared<DummyTask>();
495+ Perf<int , int > perf (task_ptr);
496+
497+ PerfAttr attr;
498+ double time = 0.0 ;
499+ attr.current_timer = [&time]() {
500+ double t = time;
501+ time += 55.0 ; // Exceeds kMaxTime (10.0)
502+ return t;
503+ };
504+
505+ perf.PipelineRun (attr);
506+
507+ testing::internal::CaptureStdout ();
508+ try {
509+ perf.PrintPerfStatistic (" test_exceed_time" );
510+ FAIL () << " Expected std::runtime_error" ;
511+ } catch (const std::runtime_error& e) {
512+ std::string error_msg = e.what ();
513+ EXPECT_NE (error_msg.find (" Task execute time need to be" ), std::string::npos);
514+ EXPECT_NE (error_msg.find (" time < 10" ), std::string::npos);
515+ EXPECT_NE (error_msg.find (" Original time in secs: 11" ), std::string::npos);
516+ }
517+ std::string output = testing::internal::GetCapturedStdout ();
518+ EXPECT_NE (output.find (" test_exceed_time:pipeline:-1.0000000000" ), std::string::npos);
519+ }
520+
521+ TEST (PerfTest, TaskRunCompletesPipelineAfterTiming) {
522+ int validation_count = 0 ;
523+ int preprocessing_count = 0 ;
524+ int run_count = 0 ;
525+ int postprocessing_count = 0 ;
526+
527+ // Create a custom task that counts method calls
528+ class CountingTask : public Task <int , int > {
529+ public:
530+ int * validation_count_;
531+ int * preprocessing_count_;
532+ int * run_count_;
533+ int * postprocessing_count_;
534+
535+ CountingTask (int * vc, int * pc, int * rc, int * ppc)
536+ : validation_count_(vc), preprocessing_count_(pc), run_count_(rc), postprocessing_count_(ppc) {}
537+
538+ bool ValidationImpl () override {
539+ (*validation_count_)++;
540+ return true ;
541+ }
542+
543+ bool PreProcessingImpl () override {
544+ (*preprocessing_count_)++;
545+ return true ;
546+ }
547+
548+ bool RunImpl () override {
549+ (*run_count_)++;
550+ return true ;
551+ }
552+
553+ bool PostProcessingImpl () override {
554+ (*postprocessing_count_)++;
555+ return true ;
556+ }
557+ };
558+
559+ auto counting_task = std::make_shared<CountingTask>(&validation_count, &preprocessing_count, &run_count, &postprocessing_count);
560+ Perf<int , int > counting_perf (counting_task);
561+
562+ PerfAttr attr;
563+ attr.num_running = 1 ;
564+
565+ counting_perf.TaskRun (attr);
566+
567+ // TaskRun should call:
568+ // 1. Validation + PreProcessing + Run (num_running times) + PostProcessing
569+ // 2. Validation + PreProcessing + Run + PostProcessing (one additional complete cycle)
570+ EXPECT_EQ (validation_count, 2 ); // Called twice
571+ EXPECT_EQ (preprocessing_count, 2 ); // Called twice
572+ EXPECT_EQ (run_count, 2 ); // Called twice (once in timing, once in final cycle)
573+ EXPECT_EQ (postprocessing_count, 2 ); // Called twice
574+ }
575+
576+ namespace test_namespace {
577+ struct TestType {};
578+ }
579+
580+ TEST (PerfTest, TemplateInstantiationWithDifferentTypes) {
581+ // Test that Perf template can be instantiated with different types
582+ auto int_task = std::make_shared<DummyTask>();
583+ Perf<int , int > int_perf (int_task);
584+
585+ auto vector_task = std::make_shared<ppc::test::TestPerfTask<std::vector<int >, int >>(std::vector<int >{1 , 2 , 3 });
586+ Perf<std::vector<int >, int > vector_perf (vector_task);
587+
588+ PerfAttr attr;
589+
590+ EXPECT_NO_THROW (int_perf.PipelineRun (attr));
591+ EXPECT_NO_THROW (vector_perf.PipelineRun (attr));
592+
593+ EXPECT_EQ (int_perf.GetPerfResults ().type_of_running , PerfResults::kPipeline );
594+ EXPECT_EQ (vector_perf.GetPerfResults ().type_of_running , PerfResults::kPipeline );
595+ }
596+
597+ TEST (PerfTest, PerfAttrCustomValues) {
598+ PerfAttr attr;
599+ attr.num_running = 10 ;
600+ attr.current_timer = []() { return 42.0 ; };
601+
602+ EXPECT_EQ (attr.num_running , 10U );
603+ EXPECT_EQ (attr.current_timer (), 42.0 );
604+ }
605+
354606TEST (TaskTest, Destructor_InvalidPipelineOrderTerminates_PartialPipeline) {
355607 {
356608 struct BadTask : Task<int , int > {
0 commit comments