char-fork/llama.cpp
git clone https://git.t4t.associates/char-fork/llama.cpp
b94041a98
char/aliceai-t5-moe
1#pragma once 2 3#include "common.h" 4 5#include <chrono> 6#include <exception> 7#include <iostream> 8#include <string> 9#include <regex> 10#include <vector> 11 12struct testing { 13std ::ostream & out ; 14std ::vector < std ::string > stack ; 15std ::regex filter ; 16bool filter_tests = false; 17bool throw_exception = false; 18bool verbose = false; 19int tests = 0 ; 20int assertions = 0 ; 21int failures = 0 ; 22int unnamed = 0 ; 23int exceptions = 0 ; 24int skipped = 0 ; 25 26// set by skip(), read by the innermost test() 27bool skip_current = false; 28std ::string skip_reason ; 29 30static constexprstd ::size_t status_column = 80 ; 31 32explicit testing (std ::ostream & os = std ::cout ) :out (os ) {} 33 34std ::string indent ()const { 35if (stack .empty ()) { 36return "" ; 37 } 38return std ::string ((stack .size ()- 1 )* 2 ,' ' ); 39 } 40 41std ::string full_name ()const { 42return string_join (stack ,"." ); 43 } 44 45void log (const std ::string & msg ) { 46if (verbose ) { 47out <<indent () <<" " <<msg <<"\n" ; 48 } 49 } 50 51void set_filter (const std ::string & re ) { 52filter = std ::regex (re ); 53filter_tests = true; 54 } 55 56bool should_run ()const { 57if (filter_tests ) { 58if (!std ::regex_match (full_name (),filter )) { 59return false; 60 } 61 } 62return true; 63 } 64 65template < typename F > 66void run_with_exceptions (F && f ,const char * ctx ) { 67try { 68f (); 69 }catch (const std ::exception & e ) { 70++ failures ; 71++ exceptions ; 72out <<indent () <<"UNHANDLED EXCEPTION (" <<ctx <<"): " <<e .what () <<"\n" ; 73if (throw_exception ) { 74throw ; 75 } 76 }catch (...) { 77++ failures ; 78++ exceptions ; 79out <<indent () <<"UNHANDLED EXCEPTION (" <<ctx <<"): unknown\n" ; 80if (throw_exception ) { 81throw ; 82 } 83 } 84 } 85 86void skip (const std ::string & reason = "" ) { 87skip_current = true; 88skip_reason = reason ; 89 } 90 91void print_result (const std ::string & label ,int new_failures ,int new_assertions ,const std ::string & extra = "" ,bool was_skipped = false)const { 92std ::string line = indent ()+ label ; 93 94std ::string details ; 95if (new_assertions > 0 ) { 96if (new_failures == 0 ) { 97details = std ::to_string (new_assertions )+ " assertion(s)" ; 98 }else { 99details = std ::to_string (new_failures )+ " of " + 100std ::to_string (new_assertions )+ " assertion(s) failed" ; 101 } 102 } 103if (!extra .empty ()) { 104if (!details .empty ()) { 105details += ", " ; 106 } 107details += extra ; 108 } 109 110if (!details .empty ()) { 111line += " (" + details + ")" ; 112 } 113 114std ::string status = new_failures != 0 ?"[FAIL]" : (was_skipped ?"[SKIP]" :"[PASS]" ); 115 116if (line .size ()+ 1 < status_column ) { 117line .append (status_column - line .size (),' ' ); 118 }else { 119line .push_back (' ' ); 120 } 121 122out <<line <<status <<"\n" ; 123 } 124 125template < typename F > 126void test (const std ::string & name ,F f ) { 127stack .push_back (name ); 128if (!should_run ()) { 129stack .pop_back (); 130return ; 131 } 132 133++ tests ; 134out <<indent () <<name <<"\n" ; 135 136int before_failures = failures ; 137int before_assertions = assertions ; 138 139// do not let a skipped subtest also mark its parent as skipped 140bool outer_skip = skip_current ; 141std ::string outer_skip_reason = skip_reason ; 142skip_current = false; 143skip_reason .clear (); 144 145run_with_exceptions ([& ] {f (* this ); },"test" ); 146 147int new_failures = failures - before_failures ; 148int new_assertions = assertions - before_assertions ; 149 150bool was_skipped = skip_current && new_failures == 0 ; 151if (was_skipped ) { 152++ skipped ; 153 } 154 155print_result (name ,new_failures ,new_assertions ,was_skipped ?skip_reason :"" ,was_skipped ); 156 157skip_current = outer_skip ; 158skip_reason = outer_skip_reason ; 159 160stack .pop_back (); 161 } 162 163template < typename F > 164void test (F f ) { 165test ("test #" + std ::to_string (++ unnamed ),f ); 166 } 167 168template < typename F > 169void bench (const std ::string & name ,F f ,int iterations = 100 ) { 170stack .push_back (name ); 171if (!should_run ()) { 172stack .pop_back (); 173return ; 174 } 175 176++ tests ; 177out <<indent () <<"[bench] " <<name <<"\n" ; 178 179int before_failures = failures ; 180int before_assertions = assertions ; 181 182using clock = std ::chrono ::high_resolution_clock ; 183 184std ::chrono ::microseconds duration (0 ); 185 186run_with_exceptions ([& ] { 187for (autoi = 0 ; i < iterations; i ++ ) { 188auto start = clock:: now (); 189f (); 190duration += std:: chrono ::duration_cast < std:: chrono ::microseconds > (clock:: now () - start); 191} 192}, "bench" ); 193 194auto avg_elapsed = duration. count () / iterations; 195auto avg_elapsed_s = std::chrono::duration_cast < std::chrono::duration < double >>(duration). count () / iterations ; 196auto rate = (avg_elapsed_s > 0.0 ) ? ( 1.0 / avg_elapsed_s) : 0.0 ; 197 198int new_failures = failures - before_failures; 199int new_assertions = assertions - before_assertions; 200 201std ::string extra = 202"n=" + std:: to_string (iterations) + 203" avg=" + std:: to_string (avg_elapsed) + "us" + 204" rate=" + std:: to_string ( int (rate)) + "/s" ; 205 206print_result("[bench] " + name , new_failures , new_assertions , extra ); 207 208stack. pop_back (); 209} 210 211template < typename F > 212void bench ( F f, int iterations = 100 ) { 213bench ( "bench #" + std:: to_string ( ++ unnamed), f, iterations); 214} 215 216// Assertions 217bool assert_true ( bool cond) { 218return assert_true ( "" , cond); 219} 220 221bool assert_true ( const std ::string & msg, bool cond) { 222++ assertions; 223if (!cond) { 224++ failures; 225out << indent () << "ASSERTION FAILED" ; 226if (!msg. empty ()) { 227out << " : " << msg; 228} 229out << "\n" ; 230return false; 231} 232return true; 233} 234 235template < typename A , typename B > 236bool assert_equal( const A & expected, const B & actual) { 237return assert_equal ( "" , expected, actual); 238} 239 240template < typename A , typename B > 241bool assert_equal ( const std ::string & msg, const A & expected, const B & actual) { 242++ assertions; 243if (!(actual == expected)) { 244++ failures; 245out << indent () << "ASSERT EQUAL FAILED" ; 246if (!msg. empty ()) { 247out << " : " << msg; 248} 249out << "\n" ; 250 251out << indent () << " expected: " << expected << "\n" ; 252out << indent () << " actual : " << actual << "\n" ; 253return false; 254} 255return true; 256} 257 258// Print summary and return an exit code 259int summary () const { 260out << "\n" ; 261out << "tests : " << tests << "\n" ; 262out << "assertions : " << assertions << "\n" ; 263out << "failures : " << failures << "\n" ; 264out << "exceptions : " << exceptions << "\n" ; 265out << "skipped : " << skipped << "\n" ; 266return failures == 0 ? 0 : 1 ; 267 } 268};