@@ -2764,7 +2764,122 @@ func TestBaseProgramCompound_OP_OPENATTR(t *testing.T) {
2764
2764
})
2765
2765
}
2766
2766
2767
- // TODO: OPEN_CONFIRM
2767
+ func TestBaseProgramCompound_OP_OPEN_CONFIRM (t * testing.T ) {
2768
+ ctrl , ctx := gomock .WithContext (context .Background (), t )
2769
+
2770
+ rootDirectory := mock .NewMockVirtualDirectory (ctrl )
2771
+ rootDirectory .EXPECT ().VirtualGetAttributes (gomock .Any (), virtual .AttributesMaskFileHandle , gomock .Any ()).
2772
+ Do (func (ctx context.Context , requested virtual.AttributesMask , attributes * virtual.Attributes ) {
2773
+ attributes .SetFileHandle ([]byte {0x2e , 0x8d , 0x48 , 0x03 , 0xc4 , 0xc3 , 0x2d , 0x6c })
2774
+ })
2775
+ handleResolver := mock .NewMockHandleResolver (ctrl )
2776
+ randomNumberGenerator := mock .NewMockSingleThreadedGenerator (ctrl )
2777
+ rebootVerifier := nfsv4_xdr.Verifier4 {0x42 , 0xa8 , 0x3f , 0xd1 , 0xde , 0x65 , 0x74 , 0x2a }
2778
+ stateIDOtherPrefix := [... ]byte {0xfa , 0xc3 , 0xf7 , 0x18 }
2779
+ clock := mock .NewMockClock (ctrl )
2780
+ program := nfsv4 .NewBaseProgram (rootDirectory , handleResolver .Call , randomNumberGenerator , rebootVerifier , stateIDOtherPrefix , clock , 2 * time .Minute , time .Minute )
2781
+
2782
+ clock .EXPECT ().Now ().Return (time .Unix (1000 , 0 ))
2783
+ clock .EXPECT ().Now ().Return (time .Unix (1001 , 0 ))
2784
+ setClientIDForTesting (ctx , t , randomNumberGenerator , program , 0x2e5550c498b2b463 )
2785
+
2786
+ t .Run ("RetransmissionSuccess" , func (t * testing.T ) {
2787
+ // It should be valid to send OPEN_CONFIRM repeatedly in
2788
+ // case of connection drops.
2789
+ leaf := mock .NewMockVirtualLeaf (ctrl )
2790
+ clock .EXPECT ().Now ().Return (time .Unix (1002 , 0 ))
2791
+ clock .EXPECT ().Now ().Return (time .Unix (1003 , 0 ))
2792
+ openUnconfirmedFileForTesting (
2793
+ ctx ,
2794
+ t ,
2795
+ randomNumberGenerator ,
2796
+ program ,
2797
+ rootDirectory ,
2798
+ leaf ,
2799
+ nfsv4_xdr.NfsFh4 {0xff , 0x27 , 0xc7 , 0x8f , 0xd5 , 0x6a , 0xfb , 0xee },
2800
+ /* shortClientID = */ 0x2e5550c498b2b463 ,
2801
+ /* seqID = */ 1205 ,
2802
+ /* stateIDOther = */ [... ]byte {
2803
+ 0xfa , 0xc3 , 0xf7 , 0x18 ,
2804
+ 0x80 , 0x57 , 0x5b , 0x95 ,
2805
+ 0x08 , 0x16 , 0x41 , 0x0a ,
2806
+ })
2807
+
2808
+ for i := int64 (0 ); i < 10 ; i ++ {
2809
+ clock .EXPECT ().Now ().Return (time .Unix (1004 + i * 2 , 0 ))
2810
+ clock .EXPECT ().Now ().Return (time .Unix (1005 + i * 2 , 0 ))
2811
+ openConfirmForTesting (
2812
+ ctx ,
2813
+ t ,
2814
+ randomNumberGenerator ,
2815
+ program ,
2816
+ nfsv4_xdr.NfsFh4 {0xff , 0x27 , 0xc7 , 0x8f , 0xd5 , 0x6a , 0xfb , 0xee },
2817
+ /* seqID = */ 1206 ,
2818
+ /* stateIDOther = */ [... ]byte {
2819
+ 0xfa , 0xc3 , 0xf7 , 0x18 ,
2820
+ 0x80 , 0x57 , 0x5b , 0x95 ,
2821
+ 0x08 , 0x16 , 0x41 , 0x0a ,
2822
+ })
2823
+ }
2824
+ })
2825
+
2826
+ t .Run ("RetransmissionWithMismatchingStateID" , func (t * testing.T ) {
2827
+ // At a minimum, the standard states that when returning
2828
+ // a cached response it is sufficient to compare the
2829
+ // original operation type and sequence ID. Let's be a
2830
+ // bit more strict and actually check whether the
2831
+ // provided state ID matches the one that was provided
2832
+ // as part of the original request.
2833
+ //
2834
+ // More details: RFC 7530, section 9.1.9, bullet point 3.
2835
+ clock .EXPECT ().Now ().Return (time .Unix (1024 , 0 ))
2836
+ clock .EXPECT ().Now ().Return (time .Unix (1025 , 0 ))
2837
+
2838
+ res , err := program .NfsV4Nfsproc4Compound (ctx , & nfsv4_xdr.Compound4args {
2839
+ Tag : "close" ,
2840
+ Argarray : []nfsv4_xdr.NfsArgop4 {
2841
+ & nfsv4_xdr.NfsArgop4_OP_PUTFH {
2842
+ Opputfh : nfsv4_xdr.Putfh4args {
2843
+ Object : nfsv4_xdr.NfsFh4 {0xff , 0x27 , 0xc7 , 0x8f , 0xd5 , 0x6a , 0xfb , 0xee },
2844
+ },
2845
+ },
2846
+ & nfsv4_xdr.NfsArgop4_OP_OPEN_CONFIRM {
2847
+ OpopenConfirm : nfsv4_xdr.OpenConfirm4args {
2848
+ Seqid : 1206 ,
2849
+ OpenStateid : nfsv4_xdr.Stateid4 {
2850
+ Seqid : 3 ,
2851
+ Other : [... ]byte {
2852
+ 0xfa , 0xc3 , 0xf7 , 0x18 ,
2853
+ 0x80 , 0x57 , 0x5b , 0x95 ,
2854
+ 0x08 , 0x16 , 0x41 , 0x0a ,
2855
+ },
2856
+ },
2857
+ },
2858
+ },
2859
+ },
2860
+ })
2861
+ require .NoError (t , err )
2862
+ require .Equal (t , & nfsv4_xdr.Compound4res {
2863
+ Tag : "close" ,
2864
+ Resarray : []nfsv4_xdr.NfsResop4 {
2865
+ & nfsv4_xdr.NfsResop4_OP_PUTFH {
2866
+ Opputfh : nfsv4_xdr.Putfh4res {
2867
+ Status : nfsv4_xdr .NFS4_OK ,
2868
+ },
2869
+ },
2870
+ & nfsv4_xdr.NfsResop4_OP_OPEN_CONFIRM {
2871
+ OpopenConfirm : & nfsv4_xdr.OpenConfirm4res_default {
2872
+ Status : nfsv4_xdr .NFS4ERR_BAD_SEQID ,
2873
+ },
2874
+ },
2875
+ },
2876
+ Status : nfsv4_xdr .NFS4ERR_BAD_SEQID ,
2877
+ }, res )
2878
+ })
2879
+
2880
+ // TODO: Any more cases we want to test?
2881
+ }
2882
+
2768
2883
// TODO: OPEN_DOWNGRADE
2769
2884
// TODO: PUTFH
2770
2885
// TODO: PUTPUBFH
0 commit comments