From ef11ad98a7440636b763fccdb67de6e2bc1b228b Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Wed, 31 Aug 2016 12:24:06 +0200 Subject: [PATCH 1/2] use stat -c for alpine linux --- lib/train/extras/stat.rb | 3 +- test/unit/extras/stat_test.rb | 81 ++++++++++++++++++++++------------- 2 files changed, 52 insertions(+), 32 deletions(-) diff --git a/lib/train/extras/stat.rb b/lib/train/extras/stat.rb index 359c875d..d045e3d8 100644 --- a/lib/train/extras/stat.rb +++ b/lib/train/extras/stat.rb @@ -34,9 +34,8 @@ def self.stat(shell_escaped_path, backend, follow_symlink) def self.linux_stat(shell_escaped_path, backend, follow_symlink) lstat = follow_symlink ? ' -L' : '' - format = backend.os.esx? ? '-c' : '--printf' + format = (backend.os.esx? || backend.os[:name] == 'alpine') ? '-c' : '--printf' res = backend.run_command("stat#{lstat} #{shell_escaped_path} 2>/dev/null #{format} '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'") - # ignore the exit_code: it is != 0 if selinux labels are not supported # on the system. diff --git a/test/unit/extras/stat_test.rb b/test/unit/extras/stat_test.rb index 56b29b91..a0e3bf07 100644 --- a/test/unit/extras/stat_test.rb +++ b/test/unit/extras/stat_test.rb @@ -1,6 +1,7 @@ # encoding: utf-8 require 'helper' require 'train/extras' +require 'train/transports/mock' describe 'stat' do let(:cls) { Train::Extras::Stat } @@ -42,27 +43,22 @@ end describe 'linux stat' do - let(:backend) { Minitest::Mock.new } + let(:backend) { + mock = Train::Transports::Mock.new(verbose: true).connection + mock.mock_os({ name: 'ubuntu', family: 'debian', release: '15.04', arch: 'x86_64' }) + mock.commands = { + "stat /path 2>/dev/null --printf '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'" => mock.mock_command('', '', '', 0), + "stat /path-stat 2>/dev/null --printf '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'" => mock.mock_command('', "360\n43ff\nroot\n0\nrootz\n1\n1444520846\n1444522445\n?", '', 0), + } + mock + } it 'ignores wrong stat results' do - res = Minitest::Mock.new - os = Minitest::Mock.new - res.expect :stdout, '' - os.expect :esx?, false - backend.expect :os, os - backend.expect :run_command, res, [String] cls.linux_stat('/path', backend, false).must_equal({}) end it 'reads correct stat results' do - res = Minitest::Mock.new - os = Minitest::Mock.new - # 43ff is 41777; linux_stat strips the 4 - res.expect :stdout, "360\n43ff\nroot\n0\nrootz\n1\n1444520846\n1444522445\n?" - os.expect :esx?, false - backend.expect :os, os - backend.expect :run_command, res, [String] - cls.linux_stat('/path', backend, false).must_equal({ + cls.linux_stat('/path-stat', backend, false).must_equal({ type: :directory, mode: 01777, owner: 'root', @@ -77,27 +73,52 @@ end describe 'esx stat' do - let(:backend) { Minitest::Mock.new } + let(:backend) { + mock = Train::Transports::Mock.new(verbose: true).connection + mock.mock_os({ name: 'vmkernel', family: 'esx', release: '5' }) + mock.commands = { + "stat /path 2>/dev/null -c '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'" => mock.mock_command('', '', '', 0), + "stat /path-stat 2>/dev/null -c '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'" => mock.mock_command('', "360\n43ff\nroot\n0\nrootz\n1\n1444520846\n1444522445\n?", '', 0), + } + mock + } it 'ignores wrong stat results' do - res = Minitest::Mock.new - os = Minitest::Mock.new - res.expect :stdout, '' - os.expect :esx?, true - backend.expect :os, os - backend.expect :run_command, res, [String] cls.linux_stat('/path', backend, false).must_equal({}) end it 'reads correct stat results' do - res = Minitest::Mock.new - os = Minitest::Mock.new - # 43ff is 41777; linux_stat strips the 4 - res.expect :stdout, "360\n43ff\nroot\n0\nrootz\n1\n1444520846\n1444522445\nC" - os.expect :esx?, true - backend.expect :os, os - backend.expect :run_command, res, [String] - cls.linux_stat('/path', backend, false).must_equal({ + cls.linux_stat('/path-stat', backend, false).must_equal({ + type: :directory, + mode: 01777, + owner: 'root', + uid: 0, + group: 'rootz', + gid: 1, + mtime: 1444522445, + size: 360, + selinux_label: nil, + }) + end + end + + describe 'alpine stat' do + let(:backend) { + mock = Train::Transports::Mock.new(verbose: true).connection + mock.mock_os({ name: 'alpine', family: 'alpine', release: nil }) + mock.commands = { + "stat /path 2>/dev/null -c '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'" => mock.mock_command('', '', '', 0), + "stat /path-stat 2>/dev/null -c '%s\n%f\n%U\n%u\n%G\n%g\n%X\n%Y\n%C'" => mock.mock_command('', "360\n43ff\nroot\n0\nrootz\n1\n1444520846\n1444522445\n?", '', 0), + } + mock + } + + it 'ignores wrong stat results' do + cls.linux_stat('/path', backend, false).must_equal({}) + end + + it 'reads correct stat results' do + cls.linux_stat('/path-stat', backend, false).must_equal({ type: :directory, mode: 01777, owner: 'root', From 0fe08685436dddb5c1b803e5032d2b1cbbc120ac Mon Sep 17 00:00:00 2001 From: Christoph Hartmann Date: Fri, 2 Sep 2016 15:29:42 +0100 Subject: [PATCH 2/2] add information to readme to run a single unit test --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index f74d937f..84ff8cc8 100644 --- a/README.md +++ b/README.md @@ -101,6 +101,12 @@ We perform `unit`, `integration` and `windows` tests. * `integration` tests run against VMs and docker containers * `windows` tests that run on appveyor for windows integration tests +## Mac/Linux + +``` +bundle exec ruby -W -Ilib:test/unit test/unit/extras/stat_test.rb +``` + ## Windows ```