Commit 78e3cbb5 authored by Nickolas Davis's avatar Nickolas Davis 🥑
Browse files

Move regression test images into subdirs, implement io library support

parent d2545316
......@@ -183,6 +183,15 @@ stages:
- build/*.png
- build/*.pnm
- build/*.pmm
- build/*/*.png
- build/*/*.pnm
- build/*/*.pmm
- build/*/*/*.png
- build/*/*/*.pnm
- build/*/*/*.pmm
- build/*/*/*/*.png
- build/*/*/*/*.pnm
- build/*/*/*/*.pmm
.cmake_memcheck_linux: &cmake_memcheck_linux
stage: test
......
data/baseline/rendering/wireframer/wf_uniform3D.png

130 Bytes | W: | H:

data/baseline/rendering/wireframer/wf_uniform3D.png

130 Bytes | W: | H:

data/baseline/rendering/wireframer/wf_uniform3D.png
data/baseline/rendering/wireframer/wf_uniform3D.png
data/baseline/rendering/wireframer/wf_uniform3D.png
data/baseline/rendering/wireframer/wf_uniform3D.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -122,9 +122,9 @@ inline VTKM_CONT vtkm::cont::DataSet ImageDifference::DoExecute(
"Difference within threshold: "
<< this->ImageDiffWithinThreshold
<< ", for pixels outside threshold: " << errorPixels.GetNumberOfValues()
<< ", with total number of pixels: " << thresholdOutput.GetNumberOfValues()
<< ", and an allowable percentage of errored pixels: "
<< this->AllowedPixelErrorRatio << ", with a total summed threshold error: "
<< ", with a total number of pixesl: " << thresholdOutput.GetNumberOfValues()
<< ", and an allowable pixel error ratio: " << this->AllowedPixelErrorRatio
<< ", with a total summed threshold error: "
<< vtkm::cont::Algorithm::Reduce(errorPixels, static_cast<FloatDefault>(0)));
vtkm::cont::DataSet clone;
......
......@@ -51,7 +51,11 @@ void TestContourFilterWedge()
result.PrintSummary(std::cout);
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "gyroid", colorTable, "contour-wedge.png", static_cast<vtkm::FloatDefault>(0.08));
result,
"gyroid",
colorTable,
"filter/contour-wedge.png",
static_cast<vtkm::FloatDefault>(0.08));
}
void TestContourFilterUniform()
......@@ -81,7 +85,7 @@ void TestContourFilterUniform()
//Y axis Flying Edge algorithm has subtle differences at a couple of boundaries
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "pointvar", colorTable, "contour-uniform.png");
result, "pointvar", colorTable, "filter/contour-uniform.png");
}
void TestContourFilterTangle()
......@@ -109,7 +113,7 @@ void TestContourFilterTangle()
//Y axis Flying Edge algorithm has subtle differences at a couple of boundaries
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "nodevar", colorTable, "contour-tangle.png");
result, "nodevar", colorTable, "filter/contour-tangle.png");
}
void TestContourFilter()
......
......@@ -52,13 +52,8 @@ void TestPointTransform()
result = vectorMagnitude.Execute(result);
result.PrintSummary(std::cout);
C canvas(512, 512);
M mapper;
vtkm::rendering::Scene scene;
auto view = vtkm::rendering::testing::GetViewPtr<M, C, V3>(
result, "pointvar", canvas, mapper, scene, colorTable, static_cast<vtkm::FloatDefault>(0.0));
VTKM_TEST_ASSERT(test_equal_images(view, "point-transform.png"));
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "pointvar", colorTable, "filter/point-transform.png");
}
} // namespace
......
......@@ -45,13 +45,8 @@ void TestSplitSharpEdges()
auto result = splitSharpEdges.Execute(dataSet);
result.PrintSummary(std::cout);
C canvas(512, 512);
M mapper;
vtkm::rendering::Scene scene;
auto view = vtkm::rendering::testing::GetViewPtr<M, C, V3>(
result, "pointvar", canvas, mapper, scene, colorTable, static_cast<vtkm::FloatDefault>(0.0));
VTKM_TEST_ASSERT(test_equal_images(view, "split-sharp-edges.png"));
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "pointvar", colorTable, "filter/split-sharp-edges.png");
}
} // namespace
......
......@@ -68,13 +68,8 @@ void TestStreamline()
result = tube.Execute(result);
result.PrintSummary(std::cout);
C canvas(512, 512);
M mapper;
vtkm::rendering::Scene scene;
auto view = vtkm::rendering::testing::GetViewPtr<M, C, V3>(
result, "pointvar", canvas, mapper, scene, colorTable, static_cast<vtkm::FloatDefault>(0.0));
VTKM_TEST_ASSERT(test_equal_images(view, "streamline.png"));
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "pointvar", colorTable, "filter/streamline.png");
}
} // namespace
......
......@@ -47,13 +47,8 @@ void TestSurfaceNormals()
auto result = surfaceNormals.Execute(dataSet);
result.PrintSummary(std::cout);
C canvas(512, 512);
M mapper;
vtkm::rendering::Scene scene;
auto view = vtkm::rendering::testing::GetViewPtr<M, C, V3>(
result, "pointvar", canvas, mapper, scene, colorTable, static_cast<vtkm::FloatDefault>(0.0));
VTKM_TEST_ASSERT(test_equal_images(view, "surface-normals.png"));
vtkm::rendering::testing::RenderAndRegressionTest<M, C, V3>(
result, "pointvar", colorTable, "filter/surface-normals.png");
}
} // namespace
......
......@@ -9,7 +9,18 @@
//============================================================================
#include <vtkm/io/FileUtils.h>
#include <vtkm/cont/ErrorBadValue.h>
#include <algorithm>
// TODO (nadavi): Once we get c++17 installed uncomment this
// #include <filesystem>
#include <errno.h>
#include <sys/stat.h>
#ifdef _MSC_VER
#include <direct.h>
#endif
namespace vtkm
{
......@@ -25,5 +36,148 @@ bool EndsWith(const std::string& value, const std::string& ending)
return std::equal(ending.rbegin(), ending.rend(), value.rbegin());
}
std::string Filename(const std::string& filePath)
{
// TODO (nadavi): Once we get c++17 installed uncomment this
// std::filesystem::path path(filePath);
// return path.filename();
#ifdef _MSC_VER
auto lastSlashPos = filePath.rfind(GetWindowsPathSeperator(filePath));
#else
auto lastSlashPos = filePath.rfind('/');
#endif
if (lastSlashPos != std::string::npos)
{
return filePath.substr(lastSlashPos + 1);
}
return filePath;
}
std::string ParentPath(const std::string& filePath)
{
// TODO (nadavi): Once we get c++17 installed uncomment this
// std::filesystem::path path(filePath);
// return path.parent_path();
#ifdef _MSC_VER
auto lastSlashPos = filePath.rfind(GetWindowsPathSeperator(filePath));
#else
auto lastSlashPos = filePath.rfind('/');
#endif
if (lastSlashPos != std::string::npos)
{
return filePath.substr(0, lastSlashPos);
}
return "";
}
bool CreateDirectoriesFromFilePath(const std::string& filePath)
{
// TODO (nadavi): Once we get c++17 installed uncomment this
// auto dir = ParentPath(filePath);
// if (dir.empty())
// {
// return false;
// }
// return std::filesystem::create_directories(dir);
auto dir = ParentPath(filePath);
if (dir.empty())
{
return false;
}
#ifdef _MSC_VER
auto ret = _mkdir(dir.c_str());
#else
mode_t mode = 0755;
auto ret = mkdir(dir.c_str(), mode);
#endif
if (ret == 0)
{
return true;
}
switch (errno)
{
case ENOENT:
{
if (!CreateDirectoriesFromFilePath(dir))
{
return false;
}
return CreateDirectoriesFromFilePath(filePath);
}
case EEXIST:
return false;
default:
return false;
}
}
std::string MergePaths(const std::string& filePathPrefix, const std::string& filePathSuffix)
{
// TODO (nadavi): Once we get c++17 installed uncomment this
// NOTE: This function may not directly mimic the c++ filesystem '/' behavior
// the edge case tests will probably need to be updated when switching.
// std::filesystem::path prefix(filePathPrefix);
// std::filesystem::path suffix(filePathSuffix);
// std::filesystem::path fullPath = prefix / suffix;
// return fullPath.string();
auto prefix = filePathPrefix;
auto suffix = filePathSuffix;
char prefixPathSeperator = '/';
char suffixPathSeperator = '/';
if (prefix.empty() && suffix.empty())
{
return "";
}
else if (prefix.empty())
{
return suffix;
}
else if (suffix.empty())
{
return prefix;
}
#ifdef _MSC_VER
prefixPathSeperator = GetWindowsPathSeperator(prefix);
suffixPathSeperator = suffix[0] == '/' || suffix[0] == '\\' ? suffix[0] : prefixPathSeperator;
#endif
if (prefix[prefix.length() - 1] == prefixPathSeperator)
{
prefix = prefix.substr(0, prefix.length() - 1);
}
if (suffix[0] == suffixPathSeperator)
{
suffix = suffix.substr(1, suffix.length());
}
return prefix + prefixPathSeperator + suffix;
}
std::string PrefixStringToFilename(const std::string& filePath, const std::string& prefix)
{
auto parentPath = ParentPath(filePath);
auto filename = Filename(filePath);
filename = prefix + filename;
return MergePaths(parentPath, filename);
}
char GetWindowsPathSeperator(const std::string& filePath)
{
auto slashType = filePath.rfind('/');
if (slashType == std::string::npos)
{
return '\\';
}
return '/';
}
} // namespace vtkm::io
} // namespace vtkm
......@@ -19,8 +19,37 @@ namespace vtkm
namespace io
{
/// \brief Checks if a provided string ends with a specific substring.
VTKM_IO_EXPORT bool EndsWith(const std::string& value, const std::string& ending);
/// \brief Returns the filename component of a filePath string.
/// Mimics the functionality of the c++17 filesystem::path filename function
VTKM_IO_EXPORT std::string Filename(const std::string& filePath);
/// \brief Returns the directory component of a filePath string.
/// Mimics the functionality of the c++17 filesystem::path parent_path function
VTKM_IO_EXPORT std::string ParentPath(const std::string& filePath);
/// \brief Creates all the directories found in a given filePath component
/// if they don't exist. Only returns true if directories are actually created.
VTKM_IO_EXPORT bool CreateDirectoriesFromFilePath(const std::string& filePath);
/// \brief Merges two filepath strings together using the correct system filepath seperator
/// EX: MergePaths("path/to/merge", "some/filename.txt") = "path/to/merge/some/filename.txt"
/// EX: MergePaths("path/to/merge/", "/some/filename.txt") = "path/to/merge/some/filename.txt"
VTKM_IO_EXPORT std::string MergePaths(const std::string& filePathPrefix,
const std::string& filePathSuffix);
/// \brief Takes the supplied prefix and prepends it to the filename for the provided filePath
/// EX: PrefixStringToFilename("/some/path/to/filename.txt", "prefix-") = "/some/path/to/prefix-filename.txt"
VTKM_IO_EXPORT std::string PrefixStringToFilename(const std::string& filePath,
const std::string& prefix);
/// \brief determine which path separator to use for windows given a provided path
/// Should return one of either '\\' or '/' depending on what the provided path uses.
/// If no seperator is found it will just return '\\'
VTKM_IO_EXPORT char GetWindowsPathSeperator(const std::string& filePath);
} // namespace vtkm::io
} // namespace vtkm
......
......@@ -8,6 +8,7 @@
// PURPOSE. See the above copyright notice for more information.
//============================================================================
#include <vtkm/io/FileUtils.h>
#include <vtkm/io/ImageWriterBase.h>
#include <vtkm/cont/Logging.h>
......@@ -75,7 +76,13 @@ void ImageWriterBase::WriteDataSet(const vtkm::cont::DataSet& dataSet,
}
}
if (CreateDirectoriesFromFilePath(this->FileName))
{
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
"Created output directory: " << ParentPath(this->FileName));
}
this->Write(width, height, colorField.GetData().AsArrayHandle<ColorArrayType>());
}
}
} // namespace vtkm::io
} // namespace vtkm
......@@ -11,6 +11,13 @@
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/io/FileUtils.h>
#ifdef _MSC_VER
#include <direct.h>
#else
#include <unistd.h>
#endif
#include <random>
#include <string>
using namespace vtkm::io;
......@@ -27,11 +34,153 @@ void TestEndsWith()
VTKM_TEST_ASSERT(EndsWith("empty_string", ""), "Ending did not match ''");
}
void TestGetWindowsPathSeperator()
{
VTKM_TEST_ASSERT(GetWindowsPathSeperator("some/test/path") == '/', "/ should be the separator");
VTKM_TEST_ASSERT(GetWindowsPathSeperator("some\\test\\path") == '\\',
"\\ should be the seperator");
VTKM_TEST_ASSERT(GetWindowsPathSeperator("some\\test/path") == '/', "Always prefer / over \\");
VTKM_TEST_ASSERT(GetWindowsPathSeperator("some/test\\path") == '/', "Always prefer / over \\");
}
void TestFilename()
{
VTKM_TEST_ASSERT(Filename("filename.txt") == "filename.txt",
"Should not affect filename without dir");
VTKM_TEST_ASSERT(Filename("test/path/filename.txt") == "filename.txt", "Should strip linux path");
VTKM_TEST_ASSERT(Filename("test/path/dir/") == "", "Should return empty string if ends in a dir");
#ifdef _MSC_VER
VTKM_TEST_ASSERT(Filename("C:\\windows\\path\\filename.txt") == "filename.txt",
"Should strip windows paths");
VTKM_TEST_ASSERT(Filename("test\\path\\dir\\") == "",
"Should return empty string if ends in a dir");
#endif
}
void TestParentPath()
{
VTKM_TEST_ASSERT(ParentPath("filename.txt") == "", "Should return empty string");
VTKM_TEST_ASSERT(ParentPath("test/path/filename.txt") == "test/path", "Should strip Linux file");
VTKM_TEST_ASSERT(ParentPath("test/path/dir/") == "test/path/dir",
"Should remove only the trailing /");
#ifdef _MSC_VER
VTKM_TEST_ASSERT(ParentPath("C:\\windows\\path\\filename.txt") == "C:\\windows\\path",
"Should strip the Windows file");
VTKM_TEST_ASSERT(ParentPath("test\\path\\dir\\") == "test\\path\\dir",
"Should remove only the trailing \\");
#endif
}
void TestCreateDirectoriesFromFilePath()
{
VTKM_TEST_ASSERT(!CreateDirectoriesFromFilePath("filename.txt"),
"no dir to create from file path, should return false");
#ifdef _MSC_VER
vtkm::Id pid = _getpid();
#else
vtkm::Id pid = getpid();
#endif
std::string baseDir;
vtkm::cont::TryExecute(
[](const vtkm::cont::DeviceAdapterId& device, vtkm::Id id, std::string& dir) {
dir = "test_dir" + std::to_string(device.GetValue()) + "_id" + std::to_string(id);
return true;
},
pid,
baseDir);
VTKM_TEST_ASSERT(CreateDirectoriesFromFilePath(baseDir + "/filename.txt"),
"Should create the " + baseDir + " dir");
VTKM_TEST_ASSERT(!CreateDirectoriesFromFilePath(baseDir + "/filename.txt"),
baseDir + " was just created, should be false");
VTKM_TEST_ASSERT(CreateDirectoriesFromFilePath(baseDir + "/test_1/"),
"Should create the 'test_1' dir");
VTKM_TEST_ASSERT(CreateDirectoriesFromFilePath(baseDir + "/test_2/test_3/file"),
"should create the full path 'test_2/test_3' in " + baseDir);
#ifdef _MSC_VER
baseDir = "win_" + baseDir;
VTKM_TEST_ASSERT(CreateDirectoriesFromFilePath(baseDir + "\\filename.txt"),
"Should create the " + baseDir + " dir");
VTKM_TEST_ASSERT(!CreateDirectoriesFromFilePath(baseDir + "\\filename.txt"),
baseDir + " was just created, should be false");
VTKM_TEST_ASSERT(CreateDirectoriesFromFilePath(baseDir + "\\test_1\\"),
"Should create the 'test_1' dir");
VTKM_TEST_ASSERT(CreateDirectoriesFromFilePath(baseDir + "\\test_2\\test_3\\file"),
"should create the full path 'test_2\\test_3' in " + baseDir);
#endif
}
void TestMergePaths()
{
VTKM_TEST_ASSERT(MergePaths("some/path", "filename.txt") == "some/path/filename.txt",
"should append filename.txt " + MergePaths("some/path", "filename.txt"));
VTKM_TEST_ASSERT(MergePaths("", "filename.txt") == "filename.txt",
"should just return the suffix");
VTKM_TEST_ASSERT(MergePaths("some/path", "") == "some/path", "should just return the prefix");
VTKM_TEST_ASSERT(MergePaths("end/in/slash/", "/start/slash") == "end/in/slash/start/slash",
"Should do correct slash merge");
VTKM_TEST_ASSERT(MergePaths("", "") == "", "Empty paths, empty return string");
#ifdef _MSC_VER
VTKM_TEST_ASSERT(MergePaths("some\\path", "filename.txt") == "some\\path\\filename.txt",
"should append filename.txt");
VTKM_TEST_ASSERT(MergePaths("some\\path", "") == "some\\path", "should just return the prefix");
VTKM_TEST_ASSERT(MergePaths("end\\in\\slash\\", "\\start\\slash") ==
"end\\in\\slash\\start\\slash",
"Should do correct slash merge");
VTKM_TEST_ASSERT(MergePaths("bad\\combo", "bad/combo") == "bad\\combo\\bad/combo",
"Should use the prefix seperator");
VTKM_TEST_ASSERT(MergePaths("bad\\combo", "/bad/combo") == "bad\\combo\\bad/combo",
"Should use the prefix seperator");
VTKM_TEST_ASSERT(MergePaths("bad/combo", "\\bad\\combo") == "bad/combo/bad\\combo",
"Should use the prefix seperator");
#endif
}
void TestPrefixStringToFilename()
{
VTKM_TEST_ASSERT(PrefixStringToFilename("some/path/filename.txt", "prefix-") ==
"some/path/prefix-filename.txt",
"should prefix file");
VTKM_TEST_ASSERT(PrefixStringToFilename("/path/here.txt", "dir/prefix-") ==
"/path/dir/prefix-here.txt",
"should prepend dir+prefix");
VTKM_TEST_ASSERT(PrefixStringToFilename("filename.txt", "prefix-") == "prefix-filename.txt",
"should prefix only file");
VTKM_TEST_ASSERT(PrefixStringToFilename("some/path/", "prefix-") == "some/path/prefix-",
"should append to file, not dir");
VTKM_TEST_ASSERT(PrefixStringToFilename("", "prefix-") == "prefix-",
"should just return the prefix-");
VTKM_TEST_ASSERT(PrefixStringToFilename("", "") == "", "Should return empty string");
VTKM_TEST_ASSERT(PrefixStringToFilename("some/path/filename.txt", "") == "some/path/filename.txt",
"should return file path");
#ifdef _MSC_VER
VTKM_TEST_ASSERT(PrefixStringToFilename("some\\path\\filename.txt", "prefix-") ==
"some\\path\\prefix-filename.txt",
"should prefix file");
VTKM_TEST_ASSERT(PrefixStringToFilename("\\path\\here.txt", "dir\\prefix-") ==
"\\path\\dir\\prefix-here.txt",
"should prepend dir+prefix");
VTKM_TEST_ASSERT(PrefixStringToFilename("some\\path\\", "prefix-") == "some\\path\\prefix-",
"should append to file, not dir");
VTKM_TEST_ASSERT(PrefixStringToFilename("some\\path\\filename.txt", "") ==
"some\\path\\filename.txt",
"should return file path");
#endif
}
void TestUtils()
{
TestEndsWith();
TestGetWindowsPathSeperator();
TestFilename();
TestParentPath();
TestCreateDirectoriesFromFilePath();
TestMergePaths();
TestPrefixStringToFilename();
}
}
} // namespace
int UnitTestFileUtils(int argc, char* argv[])
{
......
......@@ -13,11 +13,13 @@
#include <vtkm/cont/DataSet.h>
#include <vtkm/cont/Error.h>
#include <vtkm/cont/Logging.h>
#include <vtkm/cont/RuntimeDeviceTracker.h>
#include <vtkm/cont/testing/Testing.h>
#include <vtkm/filter/ImageDifference.h>
#include <vtkm/internal/Configure.h>
#include <vtkm/io/FileUtils.h>
#include <vtkm/io/ImageUtils.h>
#include <fstream>
......@@ -56,8 +58,8 @@ inline TestEqualResult test_equal_images(const std::shared_ptr<ViewType> view,
view->Paint();
view->GetCanvas().RefreshColorBuffer();
const std::string testImageName =
vtkm::cont::testing::Testing::WriteDirPath("test-" + fileNames[0]);
const std::string testImageName = vtkm::cont::testing::Testing::WriteDirPath(
vtkm::io::PrefixStringToFilename(fileNames[0], "test-"));
vtkm::io::WriteImageFile(view->GetCanvas().GetDataSet(), testImageName, "color");
for (const auto& fileName : fileNames)
......@@ -79,7 +81,8 @@ inline TestEqualResult test_equal_images(const std::shared_ptr<ViewType> view,
const std::string outputImagePath = vtkm::cont::testing::Testing::WriteDirPath(fileName);
vtkm::io::WriteImageFile(view->GetCanvas().GetDataSet(), outputImagePath, "color");
imageResult.PushMessage("File '" + fileName + "' did not exist but has been generated");
imageResult.PushMessage("File '" + fileName +
"' did not exist but has been generated here: " + outputImagePath);
testResults.PushMessage(imageResult.GetMergedMessage());
continue;
}
......@@ -110,7 +113,8 @@ inline TestEqualResult test_equal_images(const std::shared_ptr<ViewType> view,
if (writeDiff && resultDataSet.HasPointField("image-diff"))
{
const std::string diffName = vtkm::cont::testing::Testing::WriteDirPath("diff-" + fileName);
const std::string diffName = vtkm::cont::testing::Testing::WriteDirPath(
vtkm::io::PrefixStringToFilename(fileName, "diff-"));
vtkm::io::WriteImageFile(resultDataSet, diffName, "image-diff");
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment