* [gentoo-commits] proj/libbash:master commit in: scripts/, /, src/core/, bashast/, src/core/tests/
@ 2011-05-22 21:00 Petteri Räty
0 siblings, 0 replies; only message in thread
From: Petteri Räty @ 2011-05-22 21:00 UTC (permalink / raw
To: gentoo-commits
commit: 48d8c264bcf995c6c8450a710debbb3e5e6901f0
Author: Mu Qiao <qiaomuf <AT> gentoo <DOT> org>
AuthorDate: Tue May 17 10:10:42 2011 +0000
Commit: Petteri Räty <betelgeuse <AT> gentoo <DOT> org>
CommitDate: Sun May 22 16:16:34 2011 +0000
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/libbash.git;a=commit;h=48d8c264
Walker: support file stat test
---
Makefile.am | 3 +
bashast/libbashWalker.g | 6 +-
scripts/test_expr.bash | 1 +
scripts/test_expr.bash.result | 1 +
src/core/bash_condition.cpp | 115 ++++++++++++++++++++++++++
src/core/bash_condition.h | 34 ++++++++
src/core/tests/bash_condition_test.cpp | 139 ++++++++++++++++++++++++++++++++
7 files changed, 298 insertions(+), 1 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 5b33379..b680cd0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -97,6 +97,7 @@ cppunittests_SOURCES = test/run_tests.cpp \
src/core/tests/symbols_test.cpp \
src/core/tests/interpreter_test.cpp \
src/core/tests/bash_ast_test.cpp \
+ src/core/tests/bash_condition_test.cpp \
src/builtins/tests/echo_tests.cpp \
src/builtins/tests/boolean_tests.cpp \
src/builtins/tests/source_tests.cpp \
@@ -187,6 +188,8 @@ libcppbash_la_SOURCES = src/common.h \
src/core/interpreter.cpp \
src/core/interpreter.h \
src/core/symbols.hpp \
+ src/core/bash_condition.h \
+ src/core/bash_condition.cpp \
src/core/bash_ast.cpp \
src/core/bash_ast.h
diff --git a/bashast/libbashWalker.g b/bashast/libbashWalker.g
index a341109..737c7a7 100644
--- a/bashast/libbashWalker.g
+++ b/bashast/libbashWalker.g
@@ -46,6 +46,7 @@ options
#include <boost/format.hpp>
#include "builtins/builtin_exceptions.h"
+ #include "core/bash_condition.h"
#include "core/interpreter.h"
#include "cppbash_builtin.h"
@@ -510,7 +511,10 @@ common_condition returns[bool status]
// -eq, -ne, -lt, -le, -gt, or -ge for arithmetic. -nt -ot -ef for files
:^(NAME left_str=string_expr right_str=string_expr)
// -o for shell option, -z -n for string, -abcdefghkprstuwxOGLSN for files
- |^(LETTER string_expr)
+ |^(op=LETTER string_expr) {
+ $status = internal::test_unary(*reinterpret_cast<const char *>(op->getToken(op)->start),
+ $string_expr.libbash_value);
+ }
// We do not trigger pattern matching for now
|^((EQUALS|MATCH_PATTERN) left_str=string_expr right_str=string_expr) {
$status = left_str.libbash_value == right_str.libbash_value;
diff --git a/scripts/test_expr.bash b/scripts/test_expr.bash
index 1c63998..91c24fd 100644
--- a/scripts/test_expr.bash
+++ b/scripts/test_expr.bash
@@ -35,3 +35,4 @@ echo $? # 0
[[ abc = bcd && abc == abc ]] || echo true9
# abc=bcd is treated as a simple string
[[ abc=bcd && abc == abc ]] || echo wrong
+[[ -a "/" ]] && echo "true10"
diff --git a/scripts/test_expr.bash.result b/scripts/test_expr.bash.result
index 63aaa92..4be03db 100644
--- a/scripts/test_expr.bash.result
+++ b/scripts/test_expr.bash.result
@@ -16,3 +16,4 @@ true6
true7
true8
true9
+true10
diff --git a/src/core/bash_condition.cpp b/src/core/bash_condition.cpp
new file mode 100644
index 0000000..61a5826
--- /dev/null
+++ b/src/core/bash_condition.cpp
@@ -0,0 +1,115 @@
+/*
+ Please use git log for copyright holder and year information
+
+ This file is part of libbash.
+
+ libbash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ libbash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libbash. If not, see <http://www.gnu.org/licenses/>.
+ */
+///
+/// \file bash_condition.cpp
+/// \author Mu Qiao
+/// \brief implementation for Bash Conditional Expressions
+///
+#include <ctime>
+
+#include <boost/lexical_cast.hpp>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "core/interpreter_exception.h"
+
+#include "core/bash_condition.h"
+
+namespace
+{
+ bool test_file_stat(char op, const std::string& path)
+ {
+ struct stat info;
+ int status = 0;
+
+ // symbol link use lstat so we need to separate this.
+ if(op == 'L' || op == 'h')
+ return lstat(path.c_str(), &info) == 0 && S_ISLNK(info.st_mode);
+
+ status = stat(path.c_str(), &info);
+ if(status != 0 || access(path.c_str(), F_OK))
+ return false;
+
+ switch(op)
+ {
+ case 'a':
+ case 'e':
+ return true;
+ case 'b':
+ return S_ISBLK(info.st_mode);
+ case 'c':
+ return S_ISCHR(info.st_mode);
+ case 'd':
+ return S_ISDIR(info.st_mode);
+ case 'f':
+ return S_ISREG(info.st_mode);
+ case 'g':
+ return S_ISGID & info.st_mode;
+ case 'k':
+ return S_ISVTX & info.st_mode;
+ case 'p':
+ return S_ISFIFO(info.st_mode);
+ case 'r':
+ return access(path.c_str(), R_OK) == 0;
+ case 's':
+ return info.st_size > 0;
+ case 'u':
+ return S_ISUID & info.st_mode;
+ case 'w':
+ return access(path.c_str(), W_OK) == 0;
+ case 'x':
+ return access(path.c_str(), X_OK) == 0;
+ case 'O':
+ return geteuid() == info.st_uid;
+ case 'G':
+ return getegid() == info.st_gid;
+ case 'S':
+ return S_ISSOCK(info.st_mode);
+ case 'N':
+ return info.st_mtime >= info.st_atime;
+ default:
+ throw interpreter_exception(std::string("Unrecognized test operator -") + op);
+ }
+ }
+}
+
+bool internal::test_unary(char op, const std::string& target)
+{
+ switch(op)
+ {
+ case 'z':
+ return target.empty();
+ case 'n':
+ return !target.empty();
+ case 'o':
+ throw interpreter_exception("Shell option test is not supported");
+ case 't':
+ try
+ {
+ int fd = boost::lexical_cast<int>(target);
+ return isatty(fd);
+ }
+ catch(boost::bad_lexical_cast& e)
+ {
+ return false;
+ }
+ default:
+ return test_file_stat(op, target);
+ }
+}
diff --git a/src/core/bash_condition.h b/src/core/bash_condition.h
new file mode 100644
index 0000000..4e9cfa3
--- /dev/null
+++ b/src/core/bash_condition.h
@@ -0,0 +1,34 @@
+/*
+ Please use git log for copyright holder and year information
+
+ This file is part of libbash.
+
+ libbash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ libbash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libbash. If not, see <http://www.gnu.org/licenses/>.
+ */
+///
+/// \file bash_condition.h
+/// \author Mu Qiao
+/// \brief implementation for Bash Conditional Expressions
+///
+#ifndef LIBBASH_CORE_BASH_CONDITION_H_
+#define LIBBASH_CORE_BASH_CONDITION_H_
+
+#include <string>
+
+namespace internal
+{
+ bool test_unary(char op, const std::string& target);
+}
+
+#endif
diff --git a/src/core/tests/bash_condition_test.cpp b/src/core/tests/bash_condition_test.cpp
new file mode 100644
index 0000000..8bcf4b3
--- /dev/null
+++ b/src/core/tests/bash_condition_test.cpp
@@ -0,0 +1,139 @@
+/*
+ Please use git log for copyright holder and year information
+
+ This file is part of libbash.
+
+ libbash is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ libbash is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libbash. If not, see <http://www.gnu.org/licenses/>.
+*/
+///
+/// \file bash_condition_test.cpp
+/// \author Mu Qiao
+/// \brief series of unit tests for interpreter.
+///
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utime.h>
+
+#include <boost/lexical_cast.hpp>
+#include <gtest/gtest.h>
+
+#include "core/bash_condition.h"
+#include "core/interpreter_exception.h"
+
+namespace
+{
+ void set_time(const std::string& target, int ac, int mod)
+ {
+ struct utimbuf timebuf;
+ timebuf.actime = ac;
+ timebuf.modtime = mod;
+ EXPECT_EQ(0, utime(target.c_str(), &timebuf));
+ }
+
+ class file_test: public testing::Test
+ {
+ protected:
+ const std::string positive;
+ const std::string negative;
+ const std::string test_link;
+ const std::string test_fifo;
+
+ file_test(): positive("scripts/test.positive"),
+ negative("scripts/test.negative"),
+ test_link("scripts/test.link"),
+ test_fifo("scripts/test.fifo") {}
+
+ virtual void SetUp()
+ {
+ EXPECT_NE(-1, creat(positive.c_str(),
+ S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
+ ) << "Can't create " << positive << " for test";
+ set_time(positive, 0, 0);
+ EXPECT_NE(-1, creat(negative.c_str(), 0)) << "Can't create " << negative << " for test";
+ set_time(negative, 1, 0);
+ EXPECT_EQ(0, symlink(positive.c_str(), test_link.c_str()));
+ EXPECT_EQ(0, mkfifo(test_fifo.c_str(), 0));
+ }
+
+ virtual void TearDown()
+ {
+ EXPECT_EQ(0, unlink(test_fifo.c_str()));
+ EXPECT_EQ(0, unlink(positive.c_str()));
+ EXPECT_EQ(0, unlink(negative.c_str()));
+ EXPECT_EQ(0, unlink(test_link.c_str()));
+ }
+ };
+}
+
+TEST_F(file_test, file_flags_positive)
+{
+ EXPECT_TRUE(internal::test_unary('a', "/"));
+ EXPECT_TRUE(internal::test_unary('b', "/dev/root")) << "You should have /dev/root, or unit test won't pass";
+ EXPECT_TRUE(internal::test_unary('c', "/dev/random"));
+ EXPECT_TRUE(internal::test_unary('d', "/"));
+ EXPECT_TRUE(internal::test_unary('e', "/"));
+ EXPECT_TRUE(internal::test_unary('f', positive));
+ EXPECT_TRUE(internal::test_unary('g', positive));
+ EXPECT_TRUE(internal::test_unary('h', test_link));
+ EXPECT_TRUE(internal::test_unary('k', positive));
+ EXPECT_TRUE(internal::test_unary('p', test_fifo));
+ EXPECT_TRUE(internal::test_unary('r', positive));
+ EXPECT_TRUE(internal::test_unary('s', "/etc/fstab"));
+ EXPECT_TRUE(internal::test_unary('u', positive));
+ EXPECT_TRUE(internal::test_unary('w', positive));
+ EXPECT_TRUE(internal::test_unary('x', positive));
+ EXPECT_TRUE(internal::test_unary('L', test_link));
+ EXPECT_TRUE(internal::test_unary('O', positive));
+ EXPECT_TRUE(internal::test_unary('G', positive));
+ EXPECT_TRUE(internal::test_unary('S', "/dev/log")) << "You should have /dev/log, or unit test won't pass";
+ EXPECT_TRUE(internal::test_unary('N', positive));
+}
+
+TEST_F(file_test, file_flags_negative)
+{
+ EXPECT_FALSE(internal::test_unary('a', "not_exist"));
+ EXPECT_FALSE(internal::test_unary('b', negative));
+ EXPECT_FALSE(internal::test_unary('c', negative));
+ EXPECT_FALSE(internal::test_unary('d', negative));
+ EXPECT_FALSE(internal::test_unary('e', "not_exist"));
+ EXPECT_FALSE(internal::test_unary('f', "/"));
+ EXPECT_FALSE(internal::test_unary('g', negative));
+ EXPECT_FALSE(internal::test_unary('h', negative));
+ EXPECT_FALSE(internal::test_unary('k', negative));
+ EXPECT_FALSE(internal::test_unary('p', negative));
+ EXPECT_FALSE(internal::test_unary('r', negative));
+ EXPECT_FALSE(internal::test_unary('s', negative));
+ EXPECT_FALSE(internal::test_unary('t', "/dev/stdin"));
+ EXPECT_FALSE(internal::test_unary('u', negative));
+ EXPECT_FALSE(internal::test_unary('w', negative));
+ EXPECT_FALSE(internal::test_unary('x', negative));
+ EXPECT_FALSE(internal::test_unary('L', negative));
+ EXPECT_FALSE(internal::test_unary('O', "/etc/fstab"));
+ EXPECT_FALSE(internal::test_unary('G', "/etc/fstab"));
+ EXPECT_FALSE(internal::test_unary('S', negative));
+ EXPECT_FALSE(internal::test_unary('N', negative));
+}
+
+TEST(bash_condition, string_unary_operator)
+{
+ EXPECT_TRUE(internal::test_unary('z', ""));
+ EXPECT_FALSE(internal::test_unary('z', "hello"));
+
+ EXPECT_FALSE(internal::test_unary('n', ""));
+ EXPECT_TRUE(internal::test_unary('n', "hello"));
+
+ EXPECT_THROW(internal::test_unary('o', "extglob"), interpreter_exception);
+}
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2011-05-22 21:00 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-22 21:00 [gentoo-commits] proj/libbash:master commit in: scripts/, /, src/core/, bashast/, src/core/tests/ Petteri Räty
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox