// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <gflags/gflags.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctime>
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "glinterface.h"
#include "main.h"
#include "utils.h"
#include "all_tests.h"
#include "testbase.h"
using std::string;
using std::vector;
DEFINE_int32(duration, 0,
"Run all tests again and again in a loop for at least this many seconds.");
DEFINE_string(tests, "",
"Colon-separated list of tests to run; all tests if omitted.");
DEFINE_string(blacklist, "", "colon-separated list of tests to disable");
DEFINE_bool(hasty, false,
"Run a smaller set of tests with less accurate results. "
"Useful for running in BVT or debugging a failure. Implies notemp");
DEFINE_bool(list, false, "List available tests");
DEFINE_bool(notemp, false, "Skip temperature checking");
DEFINE_bool(verbose, false, "Print extra debugging messages");
bool g_verbose;
GLint g_max_texture_size;
bool g_hasty;
bool g_notemp;
bool test_is_enabled(glbench::TestBase* test,
const vector<string>& enabled_tests) {
if (enabled_tests.empty())
return true;
const char* test_name = test->Name();
for (vector<string>::const_iterator i = enabled_tests.begin();
i != enabled_tests.end(); ++i) {
// This is not very precise, but will do until there's a need for something
// more flexible.
if (strstr(test_name, i->c_str()))
return true;
}
return false;
}
bool test_is_disabled(glbench::TestBase* test,
const vector<string>& disabled_tests) {
if (disabled_tests.empty())
return false;
const char* test_name = test->Name();
for (vector<string>::const_iterator i = disabled_tests.begin();
i != disabled_tests.end(); ++i) {
// This is not very precise, but will do until there's a need for something
// more flexible.
if (strstr(test_name, i->c_str()))
return true;
}
return false;
}
void printDateTime(void) {
struct tm *ttime;
time_t tm = time(0);
char time_string[64];
ttime = localtime(&tm);
strftime(time_string, 63, "%c",ttime);
printf("# DateTime: %s\n", time_string);
}
bool PassesSanityCheck(void) {
GLint size[2];
glGetIntegerv(GL_MAX_VIEWPORT_DIMS, size);
printf("# MAX_VIEWPORT_DIMS=(%d, %d)\n", size[0], size[1]);
if (size[0] < g_width || size[1] < g_height) {
printf("# Error: MAX_VIEWPORT_DIMS=(%d, %d) are too small.\n",
size[0], size[1]);
return false;
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, size);
printf("# GL_MAX_TEXTURE_SIZE=%d\n", size[0]);
if (size[0] < g_width || size[0] < g_height) {
printf("# Error: MAX_TEXTURE_SIZE=%d is too small.\n",
size[0]);
return false;
}
g_max_texture_size = size[0];
return true;
}
int main(int argc, char *argv[]) {
SetBasePathFromArgv0(argv[0], "src");
google::ParseCommandLineFlags(&argc, &argv, false);
g_verbose = FLAGS_verbose;
g_main_gl_interface.reset(GLInterface::Create());
if (!g_main_gl_interface->Init()) {
printf("# Error: Failed to initialize %s.\n", argv[0]);
return 1;
}
printf("# board_id: %s - %s\n",
glGetString(GL_VENDOR), glGetString(GL_RENDERER));
if (!PassesSanityCheck())
return 1;
g_main_gl_interface->Cleanup();
if (argc == 1) {
printf("# Usage: %s [-save [-outdir=<directory>]] to save images\n", argv[0]);
} else {
printf("# Running: ");
for (int i = 0; i < argc; i++) printf("%s ", argv[i]);
printf("\n");
}
printDateTime();
g_hasty = FLAGS_hasty;
g_notemp = FLAGS_notemp || g_hasty;
if (!g_notemp)
g_initial_temperature = GetMachineTemperature();
vector<string> enabled_tests =
base::SplitString(FLAGS_tests, ":", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL);
vector<string> disabled_tests =
base::SplitString(FLAGS_blacklist, ":", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL);
glbench::TestBase* tests[] = {
// Please add new tests at the end of this list as tests are known to bleed
// state. Reordering them or inserting a new test may cause a change in the
// output images and MD5 causing graphics_GLBench failures.
// TODO(ihf): Fix this.
glbench::GetSwapTest(),
glbench::GetContextTest(),
glbench::GetClearTest(),
glbench::GetFillRateTest(),
glbench::GetWindowManagerCompositingTest(false),
glbench::GetWindowManagerCompositingTest(true),
glbench::GetTriangleSetupTest(),
glbench::GetYuvToRgbTest(),
glbench::GetReadPixelTest(),
glbench::GetAttributeFetchShaderTest(),
glbench::GetVaryingsAndDdxyShaderTest(),
glbench::GetTextureReuseTest(),
glbench::GetTextureUpdateTest(),
glbench::GetTextureUploadTest(),
glbench::GetFboFillRateTest(),
};
if (FLAGS_list) {
for (unsigned int i = 0; i < arraysize(tests); i++)
printf("%s\n", tests[i]->Name());
return 0;
}
uint64_t done = GetUTime() + 1000000ULL * FLAGS_duration;
do {
for (unsigned int i = 0; i < arraysize(tests); i++) {
if (!test_is_enabled(tests[i], enabled_tests) ||
test_is_disabled(tests[i], disabled_tests))
continue;
if (!g_main_gl_interface->Init()) {
printf("Initialize failed\n");
return 1;
}
glbench::ClearBuffers();
tests[i]->Run();
g_main_gl_interface->Cleanup();
}
} while (GetUTime() < done);
for (unsigned int i = 0; i < arraysize(tests); i++) {
delete tests[i];
tests[i] = NULL;
}
printDateTime();
// Signal to harness that we finished normally.
printf("@TEST_END\n");
return 0;
}