aboutsummaryrefslogtreecommitdiffstats
path: root/tests/test_bindfs.rb
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_bindfs.rb')
-rwxr-xr-xtests/test_bindfs.rb206
1 files changed, 206 insertions, 0 deletions
diff --git a/tests/test_bindfs.rb b/tests/test_bindfs.rb
new file mode 100755
index 0000000..8d5b18f
--- /dev/null
+++ b/tests/test_bindfs.rb
@@ -0,0 +1,206 @@
+#!/usr/bin/env ruby
+#
+# Copyright 2006,2007,2008,2009,2010 Martin Pärtel <martin.partel@gmail.com>
+#
+# This file is part of bindfs.
+#
+# bindfs 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.
+#
+# bindfs 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 bindfs. If not, see <http://www.gnu.org/licenses/>.
+#
+
+require 'common.rb'
+
+include Errno
+
+# FileUtils.chown turned out to be quite buggy in Ruby 1.8.7,
+# so we'll use File.chown instead.
+def chown(user, group, list)
+ user = Etc.getpwnam(user).uid if user.is_a? String
+ group = Etc.getgrnam(group).gid if group.is_a? String
+
+ list = [list] unless list.is_a? Array
+ for file in list
+ File.chown(user, group, file)
+ end
+end
+
+# Treat parameters as test names and run only those
+$only_these_tests = ARGV unless ARGV.empty?
+
+# Some useful shorthands
+$nobody_uid = nobody_uid = Etc.getpwnam('nobody').uid
+$nogroup_gid = nogroup_gid = Etc.getgrnam('nogroup').gid
+
+
+testenv("") do
+ assert { File.basename(pwd) == TESTDIR_NAME }
+end
+
+testenv("-u nobody -g nogroup") do
+ touch('src/file')
+
+ assert { File.stat('mnt/file').uid == nobody_uid }
+ assert { File.stat('mnt/file').gid == nogroup_gid }
+end
+
+testenv("-p 0600:u+D") do
+ touch('src/file')
+ chmod(0777, 'src/file')
+
+ assert { File.stat('mnt/file').mode & 0777 == 0600 }
+end
+
+testenv("--chmod-deny") do
+ touch('src/file')
+
+ assert_exception(EPERM) { chmod(0777, 'mnt/file') }
+end
+
+testenv("-u nobody -m #{Process.uid} -p 0600,u+D") do
+ touch('src/file')
+
+ assert { File.stat('mnt/file').uid == Process.uid }
+end
+
+testenv("--create-with-perms=og=r:ogd+x") do
+ touch('src/file')
+ mkdir('src/dir')
+
+ assert { File.stat('mnt/file').mode & 0077 == 0044 }
+ assert { File.stat('mnt/dir').mode & 0077 == 0055 }
+end
+
+testenv("--ctime-from-mtime") do
+ sf = 'src/file'
+ mf = 'mnt/file'
+
+ touch(sf)
+ sleep(1.1)
+ chmod(0777, mf)
+
+ assert { File.stat(mf).ctime == File.stat(mf).mtime }
+ assert { File.stat(sf).ctime > File.stat(sf).mtime }
+
+end
+
+# Define expectation for changing [uid, gid, both]
+# for each combination of chown/chgrp flags.
+chown_chgrp_test_cases = {
+ :chown_normal => {
+ :chgrp_normal => [:uid, :gid, :both],
+ :chgrp_ignore => [:uid, nil, :uid],
+ :chgrp_deny => [:uid, EPERM, EPERM]
+ },
+ :chown_ignore => {
+ :chgrp_normal => [nil, :gid, :gid],
+ :chgrp_ignore => [nil, nil, nil],
+ :chgrp_deny => [nil, EPERM, EPERM]
+ },
+ :chown_deny => {
+ :chgrp_normal => [EPERM, :gid, EPERM],
+ :chgrp_ignore => [EPERM, nil, EPERM],
+ :chgrp_deny => [EPERM, EPERM, EPERM]
+ }
+}
+
+def run_chown_chgrp_test_case(chown_flag, chgrp_flag, expectations)
+ flags = [chown_flag, chgrp_flag].map do |flag|
+ '--' + flag.to_s.sub('_', '-')
+ end.join ' '
+
+ srcfile = 'src/file'
+ mntfile = 'mnt/file'
+ tests = [
+ lambda { chown('nobody', nil, mntfile) },
+ lambda { chown(nil, 'nogroup', mntfile) },
+ lambda { chown('nobody', 'nogroup', mntfile) }
+ ]
+
+ for testcase, expect in tests.zip expectations
+ root_testenv(flags) do
+ touch(srcfile)
+ if expect.respond_to? :exception
+ assert_exception(expect) { testcase.call }
+ else
+ testcase.call
+ uid = File.stat(srcfile).uid
+ gid = File.stat(srcfile).gid
+
+ case expect
+ when :uid
+ assert { uid == $nobody_uid }
+ assert { gid != $nogroup_gid }
+ when :gid
+ assert { uid != $nobody_uid }
+ assert { gid == $nogroup_gid }
+ when :both
+ assert { uid == $nobody_uid }
+ assert { gid == $nogroup_gid }
+ when nil
+ assert { uid != $nobody_uid }
+ assert { gid != $nogroup_gid }
+ end
+ end
+ end
+ end
+end
+
+chown_chgrp_test_cases.each do |chown_flag, more|
+ more.each do |chgrp_flag, expectations|
+ run_chown_chgrp_test_case(chown_flag, chgrp_flag, expectations)
+ end
+end
+
+root_testenv("--chown-deny") do
+ touch('src/file')
+
+ assert_exception(EPERM) { chown('nobody', nil, 'mnt/file') }
+ assert_exception(EPERM) { chown('nobody', 'nogroup', 'mnt/file') }
+ chown(nil, 'nogroup', 'mnt/file')
+end
+
+testenv("--chmod-allow-x --chmod-ignore") do
+ touch('src/file')
+
+ chmod(01700, 'src/file') # sticky bit set
+
+ chmod(00077, 'mnt/file') # should change x bits; should not unset sticky bit
+ assert { File.stat('src/file').mode & 07777 == 01611 }
+
+
+ mkdir('src/dir')
+ chmod(0700, 'src/dir')
+ chmod(0077, 'mnt/dir') # bits on dir should not change
+ assert { File.stat('src/dir').mode & 0777 == 0700 }
+end
+
+testenv("--chmod-deny --chmod-allow-x") do
+ touch('src/file')
+
+ chmod(0700, 'src/file')
+
+ chmod(0700, 'mnt/file') # no-op chmod should work
+
+ assert_exception(EPERM) { chmod(0777, 'mnt/file') }
+ assert_exception(EPERM) { chmod(0000, 'mnt/file') }
+ assert_exception(EPERM) { chmod(01700, 'mnt/file') } # sticky bit
+
+ chmod(0611, 'mnt/file') # chmod that only changes x-bits should work
+ assert { File.stat('src/file').mode & 07777 == 00611 }
+
+
+ mkdir('src/dir')
+ chmod(0700, 'src/dir')
+ assert_exception(EPERM) { chmod(0700, 'mnt/dir') } # chmod on dir should not work
+end
+