rstyx 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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