1515#include " CommandLine.h"
1616#include " Validator.h"
1717#include " CrashHandler.h"
18+ #include " PluginTests.h"
1819
1920#if JUCE_MAC
2021 #include < signal.h>
@@ -322,106 +323,131 @@ static juce::StringArray mergeEnvironmentVariables (juce::StringArray args, std:
322323static juce::String getHelpMessage ()
323324{
324325 const juce::String appName (juce::JUCEApplication::getInstance ()->getApplicationName ());
325-
326- auto & newLine = juce::newLine;
327- juce::String help;
328- help << " //==============================================================================" << newLine
329- << appName << newLine
330- << juce::SystemStats::getJUCEVersion () << newLine
331- << newLine
332- << " Description: " << newLine
333- << " Validate plugins to test compatibility with hosts and verify plugin API conformance" << newLine << newLine
334- << " Usage: "
335- << newLine
336- // commands
337- << " --version" << newLine
338- << " Print pluginval version." << newLine
339- << " --validate [pathToPlugin]" << newLine
340- << " Validates the plugin at the given path." << newLine
341- << " N.B. the \" --validate\" flag is optional if the path is the last argument." << newLine
342- << " This enables you to validate a plugin with simply \" pluginval path_to_plugin\" ." << newLine
343- << newLine
344- // what to test
345- << " --sample-rates [list of comma separated sample rates]" << newLine
346- << " If specified, sets the list of sample rates at which tests will be executed" << newLine
347- << " (default=44100,48000,96000)" << newLine
348- << " --block-sizes [list of comma separated block sizes]" << newLine
349- << " If specified, sets the list of block sizes at which tests will be executed" << newLine
350- << " (default=64,128,256,512,1024)" << newLine
351- << " --random-seed [hex or int]" << newLine
352- << " Sets the random seed to use for the tests. Useful for replicating test" << newLine
353- << " environments." << newLine
354- << " --data-file [pathToFile]" << newLine
355- << " If specified, sets a path to a data file which can be used by tests to" << newLine
356- << " configure themselves. This can be useful for things like known audio output." << newLine
357- << newLine
358- // how to test
359- << " --strictness-level [1-10]" << newLine
360- << " Sets the strictness level to use. A minimum level of 5 (also the default)" << newLine
361- << " is recomended for compatibility." << newLine
362- << " Higher levels include longer, more thorough tests such as fuzzing." << newLine
363- << " --timeout-ms [numMilliseconds]" << newLine
364- << " Sets a timout which will stop validation with an error if no output from any" << newLine
365- << " test has happened for this number of ms." << newLine
366- << " By default this is 30s but can be set to \" -1\" (must be quoted) to never timeout." << newLine
367- << " --rtcheck [empty, disabled, enabled or relaxed]" << newLine
368- << " Turns on real-time saftey checks using rtcheck (macOS and Linux only)." << newLine
369- << " relaxed mode doesn't run the checks for the first processing block as a lot of plugins" << newLine
370- << " use this to allocate or initialise thread-locals (which can allocate)" << newLine
371- << newLine
372- // repeating tests
373- << " --repeat [num repeats]" << newLine
374- << " If specified repeats the tests a given number of times. Note that this does" << newLine
375- << " not delete and re-instantiate the plugin for each repeat." << newLine
376- << " --randomise" << newLine
377- << " If specified, the tests are run in a random order per repeat." << newLine
378- << newLine
379- // test selection
380- << " --skip-gui-tests" << newLine
381- << " If specified, avoids tests that create GUI windows, which can cause problems" << newLine
382- << " on headless CI systems." << newLine
383- << " --disabled-tests [pathToFile]" << newLine
384- << " If specified, sets a path to a file that should have the names of disabled" << newLine
385- << " tests on each row." << newLine
386- // external validators
387- << " --vst3validator [pathToValidator]" << newLine
388- << " If specified, this will run the VST3 validator as part of the test process." << newLine
389- << newLine
390- // output
391- << " --output-dir [pathToDir]" << newLine
392- << " If specified, sets a directory to store the log files. This can be useful" << newLine
393- << " for continuous integration." << newLine
394- << " --output-filename [filename]" << newLine
395- << " If specified, sets a filename for the log files (within 'output-dir' or" << newLine
396- << " (lacking that) the current directory." << newLine
397- << " By default, the name is constructed from the plugin metainformation" << newLine
398- << " --verbose" << newLine
399- << " If specified, outputs additional logging information. It can be useful to" << newLine
400- << " turn this off when building with CI to avoid huge log files." << newLine
401-
402- // end of options
403- << newLine
404- << " Exit code: "
405- << newLine
406- << " 0 if all tests complete successfully" << newLine
407- << " 1 if there are any errors" << newLine
408- << newLine
409- << " Additionally, you can specify any of the command line options as environment" << newLine
410- << " variables by removing prefix dashes, converting internal dashes to underscores" << newLine
411- << " and capitalising all letters, a.g." << newLine
412- << " \" --skip-gui-tests\" > \" SKIP_GUI_TESTS=1\" " << newLine
413- << " \" --timeout-ms 30000\" > \" TIMEOUT_MS=30000\" " << newLine
414- << " Specifying specific command-line options will override any environment variables" << newLine
415- << " set for that option." << newLine;
416-
417- return help;
326+ const juce::String juceVersion (juce::SystemStats::getJUCEVersion ());
327+
328+ return juce::String (R"( //==============================================================================
329+ )" + appName + R"(
330+ )" + juceVersion + R"(
331+
332+ Description:
333+ Validate plugins to test compatibility with hosts and verify plugin API conformance
334+
335+ Usage:
336+ --version
337+ Print pluginval version.
338+ --validate [pathToPlugin]
339+ Validates the plugin at the given path.
340+ N.B. the "--validate" flag is optional if the path is the last argument.
341+ This enables you to validate a plugin with simply "pluginval path_to_plugin".
342+
343+ --sample-rates [list of comma separated sample rates]
344+ If specified, sets the list of sample rates at which tests will be executed
345+ (default=44100,48000,96000)
346+ --block-sizes [list of comma separated block sizes]
347+ If specified, sets the list of block sizes at which tests will be executed
348+ (default=64,128,256,512,1024)
349+ --random-seed [hex or int]
350+ Sets the random seed to use for the tests. Useful for replicating test
351+ environments.
352+ --data-file [pathToFile]
353+ If specified, sets a path to a data file which can be used by tests to
354+ configure themselves. This can be useful for things like known audio output.
355+
356+ --strictness-level [1-10]
357+ Sets the strictness level to use. A minimum level of 5 (also the default)
358+ is recommended for compatibility.
359+ Higher levels include longer, more thorough tests such as fuzzing.
360+ --strictness-help [level]
361+ Lists all tests that run at the given strictness level (default: 5).
362+ --timeout-ms [numMilliseconds]
363+ Sets a timout which will stop validation with an error if no output from any
364+ test has happened for this number of ms.
365+ By default this is 30s but can be set to "-1" (must be quoted) to never timeout.
366+ --rtcheck [empty, disabled, enabled or relaxed]
367+ Turns on real-time safety checks using rtcheck (macOS and Linux only).
368+ relaxed mode doesn't run the checks for the first processing block as a lot of plugins
369+ use this to allocate or initialise thread-locals (which can allocate)
370+
371+ --repeat [num repeats]
372+ If specified repeats the tests a given number of times. Note that this does
373+ not delete and re-instantiate the plugin for each repeat.
374+ --randomise
375+ If specified, the tests are run in a random order per repeat.
376+
377+ --skip-gui-tests
378+ If specified, avoids tests that create GUI windows, which can cause problems
379+ on headless CI systems.
380+ --disabled-tests [pathToFile]
381+ If specified, sets a path to a file that should have the names of disabled
382+ tests on each row.
383+ --vst3validator [pathToValidator]
384+ If specified, this will run the VST3 validator as part of the test process.
385+
386+ --output-dir [pathToDir]
387+ If specified, sets a directory to store the log files. This can be useful
388+ for continuous integration.
389+ --output-filename [filename]
390+ If specified, sets a filename for the log files (within 'output-dir' or
391+ (lacking that) the current directory.
392+ By default, the name is constructed from the plugin metainformation
393+ --verbose
394+ If specified, outputs additional logging information. It can be useful to
395+ turn this off when building with CI to avoid huge log files.
396+
397+ Exit code:
398+ 0 if all tests complete successfully
399+ 1 if there are any errors
400+
401+ Additionally, you can specify any of the command line options as environment
402+ variables by removing prefix dashes, converting internal dashes to underscores
403+ and capitalising all letters, a.g.
404+ "--skip-gui-tests" > "SKIP_GUI_TESTS=1"
405+ "--timeout-ms 30000" > "TIMEOUT_MS=30000"
406+ Specifying specific command-line options will override any environment variables
407+ set for that option.
408+ )" );
418409}
419410
420411static juce::String getVersionText ()
421412{
422413 return juce::String (" pluginval" ) + " - " + VERSION;
423414}
424415
416+ static void printStrictnessHelp (int level)
417+ {
418+ level = juce::jlimit (1 , 10 , level);
419+
420+ std::cout << " Tests at strictness level " << level << " :\n\n " ;
421+
422+ auto & allTests = PluginTest::getAllTests ();
423+
424+ std::vector<PluginTest*> sortedTests;
425+ for (auto * test : allTests)
426+ sortedTests.push_back (test);
427+
428+ std::sort (sortedTests.begin (), sortedTests.end (),
429+ [] (const PluginTest* a, const PluginTest* b)
430+ { return a->strictnessLevel < b->strictnessLevel ; });
431+
432+ for (auto * test : sortedTests)
433+ {
434+ if (test->strictnessLevel > level)
435+ continue ;
436+
437+ auto descriptions = test->getDescription (level);
438+
439+ for (const auto & desc : descriptions)
440+ {
441+ std::cout << " " << desc.title ;
442+ if (desc.description .isNotEmpty ())
443+ std::cout << " : " << desc.description ;
444+ std::cout << " \n " ;
445+ }
446+ }
447+
448+ std::cout << std::endl;
449+ }
450+
425451static int getNumTestFailures (juce::UnitTestRunner& testRunner)
426452{
427453 int numFailures = 0 ;
@@ -504,6 +530,17 @@ static void performCommandLine (CommandLineValidator& validator, const juce::Arg
504530 " --run-tests" ,
505531 " Runs the internal unit tests." , juce::String (),
506532 [] (const auto &) { runUnitTests (); }});
533+ cli.addCommand ({ " --strictness-help" ,
534+ " --strictness-help [level]" ,
535+ " Lists all tests that run at the given strictness level." , juce::String (),
536+ [] (const auto & args)
537+ {
538+ int level = 5 ;
539+ auto arg = getArgumentAfterOption (args, " --strictness-help" );
540+ if (arg.text .isNotEmpty () && ! arg.isShortOption () && ! arg.isLongOption ())
541+ level = arg.text .getIntValue ();
542+ printStrictnessHelp (level);
543+ }});
507544
508545 if (const auto retValue = cli.findAndRunCommand (args); retValue != 0 )
509546 {
@@ -528,7 +565,8 @@ bool shouldPerformCommandLine (const juce::String& commandLine)
528565 return args.containsOption (" --help|-h" )
529566 || args.containsOption (" --version" )
530567 || args.containsOption (" --validate" )
531- || args.containsOption (" --run-tests" );
568+ || args.containsOption (" --run-tests" )
569+ || args.containsOption (" --strictness-help" );
532570}
533571
534572// ==============================================================================
0 commit comments