Untitled
unknown
plain_text
a year ago
4.8 kB
11
Indexable
#include <gtest/gtest.h>
#include <stdlib.h>
#include <fcntl.h>
using namespace std;
// shell to run tests on
#define SHELL "../build/shell -t"
//#define SHELL "/bin/sh"
// declarations of methods you want to test (should match exactly)
vector<string> split_string(const string& str, char delimiter = ' ');
namespace {
void Execute(std::string command, std::string expectedOutput);
void Execute(std::string command, std::string expectedOutput, std::string expectedOutputFile, std::string expectedOutputFileContent);
TEST(Shell, split_string) {
std::vector<std::string> expected;
expected = {};
EXPECT_EQ(expected, split_string(""));
EXPECT_EQ(expected, split_string(" "));
EXPECT_EQ(expected, split_string(" "));
expected = {"foo"};
EXPECT_EQ(expected, split_string("foo"));
EXPECT_EQ(expected, split_string(" foo"));
EXPECT_EQ(expected, split_string("foo "));
EXPECT_EQ(expected, split_string(" foo "));
EXPECT_EQ(expected, split_string(" foo "));
expected = {"foo", "bar"};
EXPECT_EQ(expected, split_string("foo bar"));
EXPECT_EQ(expected, split_string(" foo bar"));
EXPECT_EQ(expected, split_string(" foo bar "));
expected = {"cmd1", "arg1", "<", "inputfile", "|", "cmd2", "arg2", ">", "outputfile"};
EXPECT_EQ(expected, split_string("cmd1 arg1 < inputfile | cmd2 arg2 > outputfile"));
}
TEST(Shell, ReadFromFile) {
Execute("cat < 1", "line 1\nline 2\nline 3\nline 4");
}
TEST(Shell, ReadFromAndWriteToFile) {
Execute("cat < 1 > ../foobar", "", "../foobar", "line 1\nline 2\nline 3\nline 4");
}
TEST(Shell, ReadFromAndWriteToFileChained) {
Execute("cat < 1 | head -n 3 > ../foobar", "", "../foobar", "line 1\nline 2\nline 3\n");
Execute("cat < 1 | head -n 3 | tail -n 1 > ../foobar", "", "../foobar", "line 3\n");
}
TEST(Shell, WriteToFile) {
Execute("ls -1 > ../foobar", "", "../foobar", "1\n2\n3\n4\n");
}
TEST(Shell, Execute) {
//Execute("uname", "Linux\n");
Execute("ls", "1\n2\n3\n4\n");
Execute("ls -1", "1\n2\n3\n4\n");
}
TEST(Shell, ExecuteChained) {
Execute("ls -1 | head -n 2", "1\n2\n");
Execute("ls -1 | head -n 2 | tail -n 1", "2\n");
}
/// Custom Tests
TEST(Shell, EchoNested){
Execute("echo | echo nested", "nested\n");
}
TEST(Shell, SleepTest){
Execute("sleep 5", "");
}
TEST(Shell, SleepTestBackground){
Execute("sleep 5 &", "Process runs in background!\n");
}
//////////////// HELPERS
std::string filecontents(const std::string& str) {
std::string retval;
int fd = open(str.c_str(), O_RDONLY);
struct stat st;
if (fd >= 0 && fstat(fd, &st) == 0) {
long long size = st.st_size;
retval.resize(size_t(size));
char *current = const_cast<char*>(retval.c_str());
ssize_t left = size;
while (left > 0) {
ssize_t bytes = read(fd, current, size_t(left));
if (bytes == 0 || (bytes < 0 && errno != EINTR))
break;
if (bytes > 0) {
current += bytes;
left -= bytes;
}
}
}
if (fd >= 0)
close(fd);
return retval;
}
void filewrite(const std::string& str, std::string content) {
int fd = open(str.c_str(), O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0)
return;
while (content.size() > 0) {
ssize_t written = write(fd, content.c_str(), content.size());
if (written == -1 && errno != EINTR) {
std::cout << "error writing file '" << str << "': error " << errno << std::endl;
break;
}
if (written >= 0)
content = content.substr(size_t(written));
}
close(fd);
}
void Execute(std::string command, std::string expectedOutput) {
char buffer[512];
std::string dir = getcwd(buffer, sizeof(buffer));
filewrite("input", command);
std::string cmdstring = std::string("cd ../test-dir; " SHELL " < '") + dir + "/input' > '" + dir + "/output' 2> /dev/null";
system(cmdstring.c_str());
std::string got = filecontents("output");
EXPECT_EQ(expectedOutput, got);
}
void Execute(std::string command, std::string expectedOutput, std::string expectedOutputFile, std::string expectedOutputFileContent) {
char buffer[512];
std::string dir = getcwd(buffer, sizeof(buffer));
std::string expectedOutputLocation = "../test-dir/" + expectedOutputFile;
unlink(expectedOutputLocation.c_str());
filewrite("input", command);
std::string cmdstring = std::string("cd ../test-dir; " SHELL " < '") + dir + "/input' > '" + dir + "/output' 2> /dev/null";
int rc = system(cmdstring.c_str());
EXPECT_EQ(0, rc);
std::string got = filecontents("output");
EXPECT_EQ(expectedOutput, got) << command;
std::string gotOutputFileContents = filecontents(expectedOutputLocation);
EXPECT_EQ(expectedOutputFileContent, gotOutputFileContents) << command;
unlink(expectedOutputLocation.c_str());
}
}
Editor is loading...
Leave a Comment