rstyx 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,4 +1,9 @@
1
1
 
2
+ == 0.4.2
3
+
4
+ This is a bugfix release. Unit testing uncovered many serious bugs
5
+ in the server code.
6
+
2
7
  == 0.4.1
3
8
 
4
9
  Clarified licensing issues to LGPLv3 and Ruby License. Set up some
data/lib/rstyx/common.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://rstyx.rubyforge.org/
6
6
  # License:: GNU Lesser General Public License / Ruby License
7
7
  #
8
- # $Id: common.rb 280 2007-09-19 07:24:51Z dido $
8
+ # $Id: common.rb 298 2007-09-21 08:52:12Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -33,10 +33,10 @@ module RStyx
33
33
  ORCLOSE = 0x40
34
34
 
35
35
  # Constants related to the file type
36
- DMDIR = 0x80000000 # directory
36
+ DMDIR = 0x80000000 # directory
37
37
  DMAPPEND = 0x40000000 # append-only file
38
- DMEXCL = 0x20000000 # exclusive use file
39
- DMAUTH = 0x8000000 # file used for authentication
38
+ DMEXCL = 0x20000000 # exclusive use file
39
+ DMAUTH = 0x08000000 # file used for authentication
40
40
 
41
41
  # Maximum FID numbers and the NOFID constant.
42
42
  MAX_FID = 0xfffffffe
data/lib/rstyx/server.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://rstyx.rubyforge.org/
6
6
  # License:: GNU Lesser General Public License / Ruby License
7
7
  #
8
- # $Id: server.rb 278 2007-09-19 07:22:37Z dido $
8
+ # $Id: server.rb 302 2007-09-24 03:01:10Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -364,7 +364,8 @@ module RStyx
364
364
 
365
365
  # Create the file in the directory, add it to the directory tree,
366
366
  # and associate the new file with the given fid
367
- new_file = dir.newfile(msg.name, realperm, isdir, isapponly, isexcl)
367
+ new_file = dir.newfile(msg.name, realperm, isdir, isapponly,
368
+ isexclusive)
368
369
  dir << new_file
369
370
  @session[msg.fid] = new_file
370
371
  new_file.add_client(SFileClient.new(@session, msg.fid, msg.mode))
@@ -435,7 +436,7 @@ module RStyx
435
436
  sf.synchronize do
436
437
  @session.clunk(msg.fid)
437
438
  parent = sf.parent
438
- if @session.writable?(parent)
439
+ unless @session.writable?(parent)
439
440
  raise StyxException.new("permission denied")
440
441
  end
441
442
 
@@ -470,7 +471,7 @@ module RStyx
470
471
  unless @session.writable?(dir)
471
472
  raise StyxException.new("write permissions required on parent directory to change file name")
472
473
  end
473
- unless dir.has_child?(nstat.name)
474
+ if dir.has_child?(nstat.name)
474
475
  raise StyxException.new("cannot rename file to the name of an existing file")
475
476
  end
476
477
  sf.can_setname?(nstat.name)
@@ -479,10 +480,10 @@ module RStyx
479
480
  # Check if we are changing the length of a file
480
481
  if nstat.size != -1
481
482
  # Check if we have write permission on the file
482
- if @session.writable?(sf)
483
+ unless @session.writable?(sf)
483
484
  raise StyxException.new("write permissions required to change file length")
484
485
  end
485
- sf.can_setlength?(sf.size)
486
+ sf.can_setlength?(nstat.size)
486
487
  end
487
488
 
488
489
  # Check if we are changing the mode of a file
@@ -493,7 +494,7 @@ module RStyx
493
494
  end
494
495
 
495
496
  # Can't change the directory bit
496
- if ((nstat.mode & DMDIR == DMDIR) != sf.directory?)
497
+ if ((nstat.mode & DMDIR == DMDIR) && !sf.directory?)
497
498
  raise StyxException.new("can't change a file to a directory")
498
499
  end
499
500
  sf.can_setmode?(nstat.mode)
@@ -547,7 +548,7 @@ module RStyx
547
548
  end
548
549
 
549
550
  if nstat.size != -1
550
- sf.length = nstat.length
551
+ sf.length = nstat.size
551
552
  end
552
553
 
553
554
  if nstat.mode != MAXUINT
@@ -598,7 +599,7 @@ module RStyx
598
599
  # In this case, we can't reply with an error to the client,
599
600
  # since the tag used was invalid! If debug level is high
600
601
  # enough, simply print out an error.
601
- @log.error("#{@peername} #{e.to_s} #{msg.to_s}")
602
+ @log.error("#{@peername} #{e.class.to_s} #{msg.to_s}")
602
603
  rescue FidNotFoundException => e
603
604
  @log.error("#{@peername} unknown fid in message #{msg.to_s}")
604
605
  reply(Message::Rerror.new(:ename => "Unknown fid #{e.fid}"), tag)
@@ -607,6 +608,7 @@ module RStyx
607
608
  reply(Message::Rerror.new(:ename => "Error: #{e.message}"), tag)
608
609
  rescue Exception => e
609
610
  @log.error("#{@peername} internal error #{e.message} for #{e.to_s} at #{e.backtrace}")
611
+ reply(Message::Rerror.new(:ename => "Internal RStyx Error: #{e.message}"), tag)
610
612
  end
611
613
 
612
614
  end
data/lib/rstyx/version.rb CHANGED
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://rstyx.rubyforge.org/
6
6
  # License:: GNU Lesser General Public License / Ruby License
7
7
  #
8
- # $Id: version.rb 285 2007-09-19 07:32:56Z dido $
8
+ # $Id: version.rb 303 2007-09-24 03:02:11Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -29,7 +29,7 @@ module RStyx
29
29
 
30
30
  MAJOR = 0
31
31
  MINOR = 4
32
- TINY = 1
32
+ TINY = 2
33
33
 
34
34
  # The version of RStyx in use.
35
35
  STRING = [ MAJOR, MINOR, TINY ].join(".")
@@ -5,7 +5,7 @@
5
5
  # Homepage:: http://rstyx.rubyforge.org/
6
6
  # License:: GNU Lesser General Public License / Ruby License
7
7
  #
8
- # $Id: tc_styxservproto.rb 289 2007-09-19 07:38:07Z dido $
8
+ # $Id: tc_styxservproto.rb 301 2007-09-24 03:00:14Z dido $
9
9
  #
10
10
  #----------------------------------------------------------------------------
11
11
  #
@@ -23,7 +23,7 @@
23
23
  #
24
24
  require 'test/unit'
25
25
  require 'flexmock'
26
- require 'flexmock/test_unit'
26
+ require 'flexmock'
27
27
  require 'rstyx/server'
28
28
 
29
29
  ##
@@ -62,6 +62,14 @@ module RStyx
62
62
  return(@@mock.has_fid?(fid))
63
63
  end
64
64
 
65
+ def add_tag(t)
66
+ return(@@mock.add_tag(t))
67
+ end
68
+
69
+ def has_tag?(tag)
70
+ return(@@mock.has_tag?(tag))
71
+ end
72
+
65
73
  def execute?(styxfile)
66
74
  return(@@mock.execute?(styxfile))
67
75
  end
@@ -90,6 +98,10 @@ module RStyx
90
98
  return(@@mock.confirm_open(sf, mode))
91
99
  end
92
100
 
101
+ def user
102
+ return(@@mock.user)
103
+ end
104
+
93
105
  def iounit
94
106
  return(@@mock.iounit)
95
107
  end
@@ -135,6 +147,7 @@ class FakeConnection
135
147
  end
136
148
 
137
149
  class TestStyxServProto < Test::Unit::TestCase
150
+ include FlexMock::TestCase
138
151
  def test_tversion
139
152
  sessmock1 = flexmock
140
153
  selfmock = flexmock(:get_peername => nil)
@@ -153,8 +166,8 @@ class TestStyxServProto < Test::Unit::TestCase
153
166
  serv = FakeConnection.new(selfmock, sessmock, nil)
154
167
  resp = serv.tversion(RStyx::Message::Tversion.new(:version => "foo",
155
168
  :msize => 1024))
156
- assert_equal(RStyx::Message::Rerror, resp.class)
157
- assert_equal("Unsupported protocol version foo (must be 9P2000)", resp.ename)
169
+ assert_equal(RStyx::Message::Rversion, resp.class)
170
+ assert_equal("unknown", resp.version)
158
171
  end
159
172
 
160
173
  def test_tauth
@@ -165,7 +178,7 @@ class TestStyxServProto < Test::Unit::TestCase
165
178
  :uname => "foo",
166
179
  :aname => "bar"))
167
180
  assert_equal(RStyx::Message::Rerror, resp.class)
168
- assert_equal("Authentication methods through auth messages are not used.", resp.ename)
181
+ assert_equal("Authentication methods through auth messages are not supported.", resp.ename)
169
182
  end
170
183
 
171
184
  def test_tattach
@@ -443,13 +456,47 @@ class TestStyxServProto < Test::Unit::TestCase
443
456
  end
444
457
  end
445
458
 
446
- # Third, successful creation.
459
+ # Third, try to create a file with DMAUTH set.
460
+ FlexMock.use("sessmock") do |sessmock|
461
+ FlexMock.use("filemock") do |filemock|
462
+ sessmock.should_receive(:[]).with(42).returns(filemock)
463
+ filemock.should_receive(:directory?).returns(true)
464
+ sessmock.should_receive(:writable?).returns(true)
465
+ filemock.should_receive(:permissions).returns(0777)
466
+ serv = FakeConnection.new(selfmock, sessmock, nil)
467
+ assert_raises(RStyx::StyxException) do
468
+ resp = serv.tcreate(RStyx::Message::Tcreate.new(:fid => 42,
469
+ :mode => RStyx::OREAD,
470
+ :perm => RStyx::DMAUTH | 0644))
471
+ end
472
+ end
473
+ end
474
+
475
+ # Fourth, try to create a directory in a mode besides OREAD.
476
+ FlexMock.use("sessmock") do |sessmock|
477
+ FlexMock.use("filemock") do |filemock|
478
+ sessmock.should_receive(:[]).with(42).returns(filemock)
479
+ filemock.should_receive(:directory?).returns(true)
480
+ sessmock.should_receive(:writable?).returns(true)
481
+ filemock.should_receive(:permissions).returns(0777)
482
+ serv = FakeConnection.new(selfmock, sessmock, nil)
483
+ assert_raises(RStyx::StyxException) do
484
+ resp = serv.tcreate(RStyx::Message::Tcreate.new(:fid => 42,
485
+ :mode => RStyx::OTRUNC,
486
+ :perm => RStyx::DMDIR | 0755))
487
+ end
488
+ end
489
+ end
490
+
491
+ # Finally, successful creation.
447
492
  FlexMock.use("sessmock") do |sessmock|
448
493
  FlexMock.use("filemock") do |filemock|
449
494
  sessmock.should_receive(:[]).with(42).returns(filemock)
450
495
  filemock.should_receive(:directory?).returns(true)
451
496
  sessmock.should_receive(:writable?).returns(true)
452
- filemock.should_receive(:newfile).with("foo", 0644).returns(filemock)
497
+ filemock.should_receive(:permissions).returns(0777)
498
+ filemock.should_receive(:newfile).with("foo", 0644, false,
499
+ false, false).returns(filemock)
453
500
  filemock.should_receive(:<<).with(filemock)
454
501
  sessmock.should_receive(:[]=).with(42, filemock)
455
502
  filemock.should_receive(:add_client)
@@ -618,4 +665,514 @@ class TestStyxServProto < Test::Unit::TestCase
618
665
  assert_equal(RStyx::Message::Rclunk, resp.class)
619
666
  end
620
667
 
668
+ def test_tremove_permission_denied
669
+ # Permission denied
670
+ selfmock = flexmock(:get_peername => nil)
671
+ sessmock = flexmock
672
+ filemock = flexmock
673
+ sessmock.should_receive(:[]).with(42).returns(filemock)
674
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
675
+ sessmock.should_receive(:clunk).with(Integer).returns do |f|
676
+ assert_equal(42, f)
677
+ end
678
+ filemock.should_receive(:parent).returns(filemock)
679
+ sessmock.should_receive(:writable?).with(filemock).returns(false)
680
+ serv = FakeConnection.new(selfmock, sessmock, nil)
681
+ assert_raises(RStyx::StyxException) do
682
+ resp = serv.tremove(RStyx::Message::Tremove.new(:fid => 42))
683
+ end
684
+ end
685
+
686
+ def test_tremove_not_empty
687
+ # Directory not empty
688
+ selfmock = flexmock(:get_peername => nil)
689
+ sessmock = flexmock
690
+ filemock = flexmock
691
+ sessmock.should_receive(:[]).with(42).returns(filemock)
692
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
693
+ sessmock.should_receive(:clunk).with(Integer).returns do |f|
694
+ assert_equal(42, f)
695
+ end
696
+ filemock.should_receive(:parent).returns(filemock)
697
+ sessmock.should_receive(:writable?).with(filemock).returns(true)
698
+ filemock.should_receive(:instance_of?).with(RStyx::Server::SDirectory).returns(true)
699
+ filemock.should_receive(:child_count).returns(42)
700
+ serv = FakeConnection.new(selfmock, sessmock, nil)
701
+ assert_raises(RStyx::StyxException) do
702
+ resp = serv.tremove(RStyx::Message::Tremove.new(:fid => 42))
703
+ end
704
+ end
705
+
706
+ def test_tremove_success
707
+ selfmock = flexmock(:get_peername => nil)
708
+ sessmock = flexmock
709
+ filemock = flexmock
710
+ sessmock.should_receive(:[]).with(42).returns(filemock)
711
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
712
+ sessmock.should_receive(:clunk).with(Integer).returns do |f|
713
+ assert_equal(42, f)
714
+ end
715
+ filemock.should_receive(:parent).returns(filemock)
716
+ sessmock.should_receive(:writable?).with(filemock).returns(true)
717
+ filemock.should_receive(:remove)
718
+ sessmock.should_receive(:user).returns("foo")
719
+ filemock.should_receive(:set_mtime).with(Time, String).returns { |t,s| assert_equal("foo", s) }
720
+ serv = FakeConnection.new(selfmock, sessmock, nil)
721
+ resp = serv.tremove(RStyx::Message::Tremove.new(:fid => 42))
722
+ assert_equal(RStyx::Message::Rremove, resp.class)
723
+ end
724
+
725
+ def test_tstat
726
+ selfmock = flexmock(:get_peername => nil)
727
+ sessmock = flexmock
728
+ filemock = flexmock
729
+ filemock.should_receive(:stat)
730
+ sessmock.should_receive(:[]).with(42).returns(filemock)
731
+ serv = FakeConnection.new(selfmock, sessmock, nil)
732
+ resp = serv.tstat(RStyx::Message::Tstat.new(:fid => 42))
733
+ assert_equal(RStyx::Message::Rstat, resp.class)
734
+ end
735
+
736
+ def test_twstat_name_change_nowrite
737
+ # Test twstat for name change with no write permissions to
738
+ # parent directory
739
+ selfmock = flexmock(:get_peername => nil)
740
+ sessmock = flexmock
741
+ filemock = flexmock
742
+ sessmock.should_receive(:[]).with(42).returns(filemock)
743
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
744
+ filemock.should_receive(:parent).returns(filemock)
745
+ sessmock.should_receive(:writable?).with(filemock).returns(false)
746
+ stat = RStyx::Message::Stat.new
747
+ stat.name = "foo"
748
+ serv = FakeConnection.new(selfmock, sessmock, nil)
749
+ assert_raises(RStyx::StyxException) do
750
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
751
+ end
752
+
753
+ end
754
+
755
+ def test_twstat_name_change_conflict
756
+ # Test twstat for name change to a name of a file already
757
+ # present in the parent directory
758
+ selfmock = flexmock(:get_peername => nil)
759
+ sessmock = flexmock
760
+ filemock = flexmock
761
+ sessmock.should_receive(:[]).with(42).returns(filemock)
762
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
763
+ filemock.should_receive(:parent).returns(filemock)
764
+ sessmock.should_receive(:writable?).with(filemock).returns(true)
765
+ filemock.should_receive(:has_child?).with("foo").returns(true)
766
+ stat = RStyx::Message::Stat.new
767
+ stat.name = "foo"
768
+ serv = FakeConnection.new(selfmock, sessmock, nil)
769
+ assert_raises(RStyx::StyxException) do
770
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
771
+ end
772
+ end
773
+
774
+ def test_twstat_name_change_success
775
+ # test twstat for successful name change
776
+ selfmock = flexmock(:get_peername => nil)
777
+ sessmock = flexmock
778
+ filemock = flexmock
779
+ sessmock.should_receive(:[]).with(42).returns(filemock)
780
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
781
+ filemock.should_receive(:parent).returns(filemock)
782
+ sessmock.should_receive(:writable?).with(filemock).returns(true)
783
+ filemock.should_receive(:has_child?).with("foo").returns(false)
784
+ stat = RStyx::Message::Stat.new
785
+ stat.name = "foo"
786
+ stat.size = -1
787
+ stat.mode = RStyx::MAXUINT
788
+ stat.mtime = RStyx::MAXUINT
789
+ stat.dtype = 0xffff
790
+ stat.dev = 0xffffffff
791
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
792
+ 0xffffffffffffffff)
793
+ stat.gid = stat.uid = stat.muid = ""
794
+ stat.atime = 0xffffffff
795
+ filemock.should_receive(:can_setname?)
796
+ filemock.should_receive(:name=).with(String).returns { |s| assert_equal("foo", s) }
797
+ serv = FakeConnection.new(selfmock, sessmock, nil)
798
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
799
+ assert_equal(RStyx::Message::Rwstat, resp.class)
800
+ end
801
+
802
+ def test_twstat_size_noperm
803
+ # permission denied for file size change
804
+ # Test twstat for name change with no write permissions to
805
+ # parent directory
806
+ selfmock = flexmock(:get_peername => nil)
807
+ sessmock = flexmock
808
+ filemock = flexmock
809
+ sessmock.should_receive(:[]).with(42).returns(filemock)
810
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
811
+ sessmock.should_receive(:writable?).with(filemock).returns(false)
812
+ stat = RStyx::Message::Stat.new
813
+ stat.name = ""
814
+ stat.size = 42
815
+ serv = FakeConnection.new(selfmock, sessmock, nil)
816
+ assert_raises(RStyx::StyxException) do
817
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
818
+ end
819
+
820
+ end
821
+
822
+ def test_twstat_size_success
823
+ # test twstat for successful size change
824
+ selfmock = flexmock(:get_peername => nil)
825
+ sessmock = flexmock
826
+ filemock = flexmock
827
+ sessmock.should_receive(:[]).with(42).returns(filemock)
828
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
829
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
830
+ sessmock.should_receive(:writable?).with(filemock).returns(true)
831
+ stat = RStyx::Message::Stat.new
832
+ stat.name = ""
833
+ stat.size = 42
834
+ stat.mode = RStyx::MAXUINT
835
+ stat.mtime = RStyx::MAXUINT
836
+ stat.dtype = 0xffff
837
+ stat.dev = 0xffffffff
838
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
839
+ 0xffffffffffffffff)
840
+ stat.gid = stat.uid = stat.muid = ""
841
+ stat.atime = 0xffffffff
842
+ filemock.should_receive(:can_setlength?).with(Integer).returns { |s| assert_equal(42, s) }
843
+ filemock.should_receive(:length=).with(Integer).returns { |s| assert_equal(42, s) }
844
+ serv = FakeConnection.new(selfmock, sessmock, nil)
845
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
846
+ assert_equal(RStyx::Message::Rwstat, resp.class)
847
+ end
848
+
849
+ def test_twstat_mode_not_owner
850
+ # test twstat error condition, where mode changer is not the owner of
851
+ # the file.
852
+ selfmock = flexmock(:get_peername => nil)
853
+ sessmock = flexmock
854
+ filemock = flexmock
855
+ sessmock.should_receive(:[]).with(42).returns(filemock)
856
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
857
+ sessmock.should_receive(:user).returns("foo")
858
+ filemock.should_receive(:uid).returns("bar")
859
+ stat = RStyx::Message::Stat.new
860
+ stat.name = ""
861
+ stat.size = -1
862
+ stat.mode = 0644
863
+ serv = FakeConnection.new(selfmock, sessmock, nil)
864
+ assert_raises(RStyx::StyxException) do
865
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
866
+ end
867
+ end
868
+
869
+ def test_twstat_mode_add_dirbit
870
+ # test twstat error condition, where the mode of an ordinary file is
871
+ # to be changed to that of a directory.
872
+ selfmock = flexmock(:get_peername => nil)
873
+ sessmock = flexmock
874
+ filemock = flexmock
875
+ sessmock.should_receive(:[]).with(42).returns(filemock)
876
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
877
+ sessmock.should_receive(:user).returns("foo")
878
+ filemock.should_receive(:uid).returns("foo")
879
+ filemock.should_receive(:directory?).returns(false)
880
+ stat = RStyx::Message::Stat.new
881
+ stat.name = ""
882
+ stat.size = -1
883
+ stat.mode = 0644 | RStyx::DMDIR
884
+ serv = FakeConnection.new(selfmock, sessmock, nil)
885
+ assert_raises(RStyx::StyxException) do
886
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
887
+ end
888
+ end
889
+
890
+ def test_twstat_mode_success
891
+ # test twstat for successful mode change
892
+ selfmock = flexmock(:get_peername => nil)
893
+ sessmock = flexmock
894
+ filemock = flexmock
895
+ sessmock.should_receive(:[]).with(42).returns(filemock)
896
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
897
+ sessmock.should_receive(:user).returns("foo")
898
+ filemock.should_receive(:uid).returns("foo")
899
+ filemock.should_receive(:directory?).returns(false)
900
+ filemock.should_receive(:can_setmode?)
901
+ filemock.should_receive(:mode=).with(Integer).returns { |m| assert_equal(0644, m) }
902
+ stat = RStyx::Message::Stat.new
903
+ stat.name = ""
904
+ stat.size = -1
905
+ stat.mode = 0644
906
+ stat.mtime = RStyx::MAXUINT
907
+ stat.dtype = 0xffff
908
+ stat.dev = 0xffffffff
909
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
910
+ 0xffffffffffffffff)
911
+ stat.gid = stat.uid = stat.muid = ""
912
+ stat.atime = 0xffffffff
913
+ serv = FakeConnection.new(selfmock, sessmock, nil)
914
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
915
+ end
916
+
917
+ def test_twstat_mtime_not_owner
918
+ # test twstat error condition, where mtime changer is not the owner of
919
+ # the file.
920
+ selfmock = flexmock(:get_peername => nil)
921
+ sessmock = flexmock
922
+ filemock = flexmock
923
+ sessmock.should_receive(:[]).with(42).returns(filemock)
924
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
925
+ sessmock.should_receive(:user).returns("foo")
926
+ filemock.should_receive(:uid).returns("bar")
927
+ stat = RStyx::Message::Stat.new
928
+ stat.name = ""
929
+ stat.size = -1
930
+ stat.mode = RStyx::MAXUINT
931
+ stat.mtime = Time.now.to_i
932
+ serv = FakeConnection.new(selfmock, sessmock, nil)
933
+ assert_raises(RStyx::StyxException) do
934
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
935
+ end
936
+ end
937
+
938
+ def test_twstat_mtime_success
939
+ # test twstat for successful mtime change
940
+ selfmock = flexmock(:get_peername => nil)
941
+ sessmock = flexmock
942
+ filemock = flexmock
943
+ sessmock.should_receive(:[]).with(42).returns(filemock)
944
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
945
+ sessmock.should_receive(:user).returns("foo")
946
+ filemock.should_receive(:uid).returns("foo")
947
+ filemock.should_receive(:directory?).returns(false)
948
+ filemock.should_receive(:can_setmtime?)
949
+ filemock.should_receive(:mtime=).with(Integer).returns { |m| assert_equal(1190545938, m) }
950
+ stat = RStyx::Message::Stat.new
951
+ stat.name = ""
952
+ stat.size = -1
953
+ stat.mode = RStyx::MAXUINT
954
+ stat.mtime = 1190545938
955
+ stat.dtype = 0xffff
956
+ stat.dev = 0xffffffff
957
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
958
+ 0xffffffffffffffff)
959
+ stat.gid = stat.uid = stat.muid = ""
960
+ stat.atime = 0xffffffff
961
+ serv = FakeConnection.new(selfmock, sessmock, nil)
962
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
963
+ assert_equal(RStyx::Message::Rwstat, resp.class)
964
+ end
965
+
966
+ def test_twstat_misc_failures
967
+ # test twstat for miscellaneous failure modes
968
+ # Try to change group ID (not permitted by an RStyx server)
969
+ selfmock = flexmock(:get_peername => nil)
970
+ sessmock = flexmock
971
+ filemock = flexmock
972
+ sessmock.should_receive(:[]).with(42).returns(filemock)
973
+ filemock.should_receive(:synchronize).with(Proc).returns { |block| block.call }
974
+ stat = RStyx::Message::Stat.new
975
+ stat.name = ""
976
+ stat.size = -1
977
+ stat.mode = RStyx::MAXUINT
978
+ stat.mtime = RStyx::MAXUINT
979
+ stat.dtype = 0xfffff
980
+ stat.dev = 0xffffffff
981
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
982
+ 0xffffffffffffffff)
983
+ stat.gid = "foo"
984
+ stat.uid = stat.muid = ""
985
+ stat.atime = 0xffffffff
986
+ serv = FakeConnection.new(selfmock, sessmock, nil)
987
+ assert_raises(RStyx::StyxException) do
988
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
989
+ end
990
+
991
+ # Try changing dtype
992
+ stat = RStyx::Message::Stat.new
993
+ stat.name = ""
994
+ stat.size = -1
995
+ stat.mode = RStyx::MAXUINT
996
+ stat.mtime = RStyx::MAXUINT
997
+ stat.dtype = 0xff00
998
+ stat.dev = 0xffffffff
999
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
1000
+ 0xffffffffffffffff)
1001
+ stat.gid = stat.uid = stat.muid = ""
1002
+ stat.atime = 0xffffffff
1003
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1004
+ assert_raises(RStyx::StyxException) do
1005
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1006
+ end
1007
+
1008
+ # Try changing dev
1009
+ stat.dtype = 0xffff
1010
+ stat.dev = 0xdeadbeef
1011
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1012
+ assert_raises(RStyx::StyxException) do
1013
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1014
+ end
1015
+
1016
+ # Try changing Qid
1017
+ stat.dev = 0xffffffff
1018
+ stat.qid = RStyx::Message::Qid.new(0xfe, 0xf000baaa, 0xdeadbeeff00baaa)
1019
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1020
+ assert_raises(RStyx::StyxException) do
1021
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1022
+ end
1023
+
1024
+ # Try changing atime
1025
+ stat.qid = RStyx::Message::Qid.new(0xff, 0xffffffff,
1026
+ 0xffffffffffffffff)
1027
+ stat.atime = Time.now.to_i
1028
+ assert_raises(RStyx::StyxException) do
1029
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1030
+ end
1031
+
1032
+ # try changing uid
1033
+ stat.atime = 0xffffffff
1034
+ stat.uid = "foo"
1035
+ assert_raises(RStyx::StyxException) do
1036
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1037
+ end
1038
+
1039
+ # try changing muid
1040
+ stat.uid = ""
1041
+ stat.muid = "foo"
1042
+ assert_raises(RStyx::StyxException) do
1043
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1044
+ end
1045
+
1046
+ # Try an empty change
1047
+ stat.muid = ""
1048
+ resp = serv.twstat(RStyx::Message::Twstat.new(:stat => stat, :fid => 42))
1049
+ assert_equal(RStyx::Message::Rwstat, resp.class)
1050
+ end
1051
+
1052
+ def test_reply
1053
+ msg = RStyx::Message::Rversion.new(:version => "9P2000",
1054
+ :msize => 8216)
1055
+ selfmock = flexmock(:get_peername => nil)
1056
+ sessmock = flexmock
1057
+ sessmock.should_receive(:has_tag?).returns(true)
1058
+ selfmock.should_receive(:send_data).with(String).returns do |msg|
1059
+ umsg = RStyx::Message::StyxMessage.from_bytes(msg)
1060
+ assert_equal(RStyx::Message::Rversion, umsg.class)
1061
+ assert_equal("9P2000", umsg.version)
1062
+ assert_equal(8216, umsg.msize)
1063
+ assert_equal(42, umsg.tag)
1064
+ end
1065
+ sessmock.should_receive(:release_tag).with(Integer).returns { |t| assert_equal(42, t) }
1066
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1067
+ resp = serv.reply(msg, 42)
1068
+ end
1069
+
1070
+ def test_process_styxmsg_badtag
1071
+ selfmock = flexmock(:get_peername => nil)
1072
+ sessmock = flexmock
1073
+ logmock = flexmock
1074
+ sessmock.should_receive(:add_tag).with(Integer).returns do |t|
1075
+ assert_equal(42, t)
1076
+ raise RStyx::TagInUseException.new(t)
1077
+ end
1078
+ logmock.should_receive(:error).with(String).returns do |s|
1079
+ assert_equal("(unknown peer) RStyx::TagInUseException (Tversion :tag=>\"42\" :msize=>\"8216\" :version=>\"9P2000\")", s)
1080
+ end
1081
+ msg = RStyx::Message::Tversion.new(:version => "9P2000",
1082
+ :msize => 8216,
1083
+ :tag => 42)
1084
+ serv = FakeConnection.new(selfmock, sessmock, nil, logmock)
1085
+ serv.process_styxmsg(msg)
1086
+ end
1087
+
1088
+ def test_process_styxmsg_badfid
1089
+ selfmock = flexmock(:get_peername => nil)
1090
+ sessmock = flexmock
1091
+ sessmock.should_receive(:add_tag).with(Integer).returns do |t|
1092
+ assert_equal(42, t)
1093
+ end
1094
+ sessmock.should_receive(:[]).with(Integer).returns do |t|
1095
+ assert_equal(42, t)
1096
+ raise RStyx::FidNotFoundException.new(t)
1097
+ end
1098
+ msg = RStyx::Message::Twrite.new(:fid => 42,
1099
+ :tag => 42)
1100
+ sessmock.should_receive(:has_tag?).returns(true)
1101
+ selfmock.should_receive(:send_data).with(String).returns do |msg|
1102
+ umsg = RStyx::Message::StyxMessage.from_bytes(msg)
1103
+ assert_equal(RStyx::Message::Rerror, umsg.class)
1104
+ end
1105
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1106
+ sessmock.should_receive(:release_tag).with(Integer).returns { |t| assert_equal(42, t) }
1107
+
1108
+ serv.process_styxmsg(msg)
1109
+ end
1110
+
1111
+ def test_process_styxmsg_emptyreply
1112
+ msgmock = flexmock
1113
+ selfmock = flexmock(:get_peername => nil)
1114
+ sessmock = flexmock
1115
+ sessmock.should_receive(:add_tag).with(42)
1116
+ sessmock.should_receive(:[]).with(Integer).returns do |t|
1117
+ assert_equal(42, t)
1118
+ raise RStyx::FidNotFoundException.new(t)
1119
+ end
1120
+ sessmock.should_receive(:has_tag?).returns(true)
1121
+ selfmock.should_receive(:send_data).with(String).returns do |msg|
1122
+ umsg = RStyx::Message::StyxMessage.from_bytes(msg)
1123
+ assert_equal(RStyx::Message::Rerror, umsg.class)
1124
+ end
1125
+ selfmock.should_receive(:flexmock).returns(nil)
1126
+ msgmock.should_receive(:tag).returns(42)
1127
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1128
+ sessmock.should_receive(:release_tag).with(Integer).returns { |t| assert_equal(42, t) }
1129
+
1130
+ serv.process_styxmsg(msgmock)
1131
+ end
1132
+
1133
+ def test_process_styxmsg_internalerror
1134
+ msgmock = flexmock
1135
+ selfmock = flexmock(:get_peername => nil)
1136
+ sessmock = flexmock
1137
+ sessmock.should_receive(:add_tag).with(42)
1138
+ sessmock.should_receive(:[]).with(Integer).returns do |t|
1139
+ assert_equal(42, t)
1140
+ raise RStyx::FidNotFoundException.new(t)
1141
+ end
1142
+ selfmock.should_receive(:absorber).returns(nil)
1143
+ sessmock.should_receive(:has_tag?).returns(true)
1144
+ selfmock.should_receive(:send_data).with(String).returns do |msg|
1145
+ umsg = RStyx::Message::StyxMessage.from_bytes(msg)
1146
+ assert_equal(RStyx::Message::Rerror, umsg.class)
1147
+ end
1148
+ selfmock.should_receive(:flexmock).returns { raise "error" }
1149
+ msgmock.should_receive(:tag).returns(42)
1150
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1151
+ sessmock.should_receive(:release_tag).with(Integer).returns { |t| assert_equal(42, t) }
1152
+
1153
+ serv.process_styxmsg(msgmock)
1154
+ end
1155
+
1156
+ def test_process_styxmsg_success
1157
+ selfmock = flexmock(:get_peername => nil)
1158
+ sessmock = flexmock
1159
+ sessmock.should_receive(:add_tag).with(Integer).returns do |t|
1160
+ assert_equal(42, t)
1161
+ end
1162
+ sessmock.should_receive(:[]).with(Integer).returns do |t|
1163
+ assert_equal(42, t)
1164
+ end
1165
+ msg = RStyx::Message::Tclunk.new(:fid => 42, :tag => 42)
1166
+ sessmock.should_receive(:clunk).with(42)
1167
+ sessmock.should_receive(:has_tag?).returns(true)
1168
+ selfmock.should_receive(:send_data).with(String).returns do |msg|
1169
+ umsg = RStyx::Message::StyxMessage.from_bytes(msg)
1170
+ assert_equal(RStyx::Message::Rclunk, umsg.class)
1171
+ end
1172
+ serv = FakeConnection.new(selfmock, sessmock, nil)
1173
+ sessmock.should_receive(:release_tag).with(Integer).returns { |t| assert_equal(42, t) }
1174
+
1175
+ serv.process_styxmsg(msg)
1176
+ end
1177
+
621
1178
  end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
3
3
  specification_version: 1
4
4
  name: rstyx
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.4.1
7
- date: 2007-09-19 00:00:00 +08:00
6
+ version: 0.4.2
7
+ date: 2007-09-24 00:00:00 +08:00
8
8
  summary: RStyx is a Ruby implementation of the 9P2000/Styx distributed file protocol used on Plan 9 and Inferno.
9
9
  require_paths:
10
10
  - lib