if (path.empty())
return false;
if (stat(path.c_str(), &s))
- throw PluginException("Can not get info for file: " + path);
+ {
+ if (errno == ENOENT)
+ {
+ // file not found, try to create it
+ ofstream f(path);
+ if (!f.good())
+ throw PluginException("Can not create output file: " + path);
+ // try again
+ int res = stat(path.c_str(), &s);
+ (void) res;
+ // on this step everythink should be fine, since we just created file
+ assert(!res);
+ return true;
+ }
+ else
+ throw PluginException("Can not get info for file: " + path);
+ }
+ // check that selected file is regular or char device(to accept /dev/null, and simular)
+ if (!(s.st_mode & (S_IFREG | S_IFCHR)))
+ throw PluginException("Not a regular file: " + path);
return true;
}
// check that header, code and model file paths refers to different files.
// Exception: stdout could be common output stream
struct stat headerStat, codeStat, modelStat;
- bool skipHeader = fillFileStats(_headerFile, headerStat);
- bool skipCode = fillFileStats(_codeFile, codeStat);
- bool skipModel = fillFileStats(_modelFile, modelStat);
+ bool checkHeader = fillFileStats(_headerFile, headerStat);
+ bool checkCode = fillFileStats(_codeFile, codeStat);
+ bool checkModel = fillFileStats(_modelFile, modelStat);
- if ((!skipHeader && !skipCode && areFilesEqual(headerStat, codeStat)) ||
- (!skipHeader && !skipModel && areFilesEqual(headerStat, modelStat)) ||
- (!skipCode && !skipModel && areFilesEqual(codeStat, modelStat)))
+ if ((checkHeader && checkCode && areFilesEqual(headerStat, codeStat)) ||
+ (checkHeader && checkModel && areFilesEqual(headerStat, modelStat)) ||
+ (checkCode && checkModel && areFilesEqual(codeStat, modelStat)))
{
throw PluginException("output files should not be equal");
}
--- /dev/null
+#include "generator.h"
+#include "PluginException.h"
+
+#include <gtest/gtest.h>
+
+#include <fstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <cstdio>
+
+using namespace std;
+using namespace nncc::contrib;
+using namespace nncc::contrib::backend::soft;
+
+static bool isFileExists(const string &path)
+{
+ ifstream f(path);
+ return f.good();
+}
+
+static void createFile(const string &path)
+{
+ assert(!isFileExists(path));
+ ofstream f(path);
+ assert(f.good());
+ f << "hello world\n";
+}
+
+static void createDir(const string &path)
+{
+ int res = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ assert(!res);
+}
+
+static void deleteFile(const string &path)
+{
+ int res = remove(path.c_str());
+ assert(!res && "failed to remove file");
+}
+
+static void deleteDir(const string &path)
+{
+ int res = rmdir(path.c_str());
+ assert(!res && "failed to remove dir");
+}
+
+TEST(Generator, check_path_consistency)
+{
+ // assume here that c++ and c code generators behave identically in terms of parameters check
+ // test only c++ generator
+ const char *TEST_FILE1 = "test_file1";
+ const char *TEST_FILE2 = "test_file2";
+ const char *TEST_DIR = "test_dir";
+
+ // iterate this arrays to check that all arguments are working equally
+ const char *fileNames1[] = {"", "" , TEST_FILE1, "", ""};
+ const char *fileNames2[] = {TEST_FILE1, TEST_FILE1, "", TEST_FILE1, TEST_FILE1};
+ const char *fileNames3[] = {TEST_FILE1, TEST_FILE2, "", TEST_FILE1, TEST_FILE2};
+ const char *dirNames[] = {"", "" , TEST_DIR, "", ""};
+
+ assert(!isFileExists(TEST_DIR) && "remove test_dir");
+ assert(!isFileExists(TEST_FILE2) && "remove test_file2");
+ createDir(TEST_DIR);
+ for (int i = 0; i < 3; ++i)
+ {
+ // check that test file is created
+ assert(!isFileExists(TEST_FILE1) && "remove test_file1");
+ CPPCodeGenerator::create(fileNames1[i], fileNames1[i + 1], fileNames1[i + 2]);
+ ASSERT_TRUE(isFileExists(TEST_FILE1));
+ // file already exists
+ struct stat s1;
+ int res = stat(TEST_FILE1, &s1);
+ assert(!res);
+ CPPCodeGenerator::create(fileNames1[i], fileNames1[i + 1], fileNames1[i + 2]);
+ struct stat s2;
+ res = stat(TEST_FILE1, &s2);
+ assert(!res);
+ deleteFile(TEST_FILE1);
+ // check that file is not changed at this point
+ ASSERT_EQ(s1.st_ino, s2.st_ino);
+ ASSERT_EQ(s1.st_size, s2.st_size);
+ // check that dir is not valid output
+ EXPECT_THROW(CPPCodeGenerator::create(dirNames[i], dirNames[i + 1], dirNames[i + 2]), PluginException);
+ // check that equal files are not permitted
+ EXPECT_THROW(CPPCodeGenerator::create(fileNames2[i], fileNames2[i + 1], fileNames2[i + 2]), PluginException);
+ // check that different files are ok
+ CPPCodeGenerator::create(fileNames3[i], fileNames3[i + 1], fileNames3[i + 2]);
+ deleteFile(TEST_FILE1);
+ }
+ deleteDir(TEST_DIR);
+ deleteFile(TEST_FILE2);
+}
+