2011-03-02 06:23:05

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 00/17] add some test case for pynfs41

Add some test case for pynfs41 which according to rfc5661.



thanks,
Mi Jinlong



2011-03-14 19:27:33

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 15/17] CLNT: test lock before RECLAIM_COMPLETE

On Wed, Mar 02, 2011 at 02:36:15PM +0800, Mi Jinlong wrote:
> Signed-off-by: Mi Jinlong <[email protected]>

I'm getting failures I don't understand on these reclaim complete tests
too.

--b.

> ---
> nfs4.1/server41tests/st_reclaim_complete.py | 26 ++++++++++++++++++++++++++
> 1 files changed, 26 insertions(+), 0 deletions(-)
>
> diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
> index 45ac9ad..a94f2ad 100644
> --- a/nfs4.1/server41tests/st_reclaim_complete.py
> +++ b/nfs4.1/server41tests/st_reclaim_complete.py
> @@ -50,3 +50,29 @@ def testReclaimAfterRECC(t, env):
>
> res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
> check(res, NFS4ERR_NO_GRACE)
> +
> +def testLockBeforeRECC(t, env):
> + """After a client establishes a new client ID, if non-reclaim
> + locking operations are done before the RECLAIM_COMPLETE,
> + error NFS4ERR_GRACE will be returned. rfc5661 18.51.3
> +
> + FLAGS: all
> + CODE: RECC3
> + """
> + name = env.testname(t)
> + c = env.c1.new_client(name)
> + sess = c.create_session()
> +
> + fname = "owner_%s" % name
> + path = sess.c.homedir + [name]
> + res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
> + check(res)
> +
> + oseqid = res.resarray[2].stateid
> + cfh = res.resarray[3].object
> + owner = open_owner4(0, "My Open Owner")
> + otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
> + lowner = locker4(TRUE, otlowner)
> +
> + res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
> + check(res, NFS4ERR_NO_GRACE)
> --
> 1.7.4.1
>
>
>

2011-03-28 08:58:23

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH v2 3/5] CLNT: test reclaim after RECLAIM_COMPLETE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_reclaim_complete.py | 50 +++++++++++++++++++++++++++
1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index 5e3174c..4c9fc37 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -1,9 +1,18 @@
from st_create_session import create_session
from nfs4_const import *
from environment import check, fail, use_obj, create_file
+from nfs4_type import open_owner4, locker4, open_to_lock_owner4
import nfs4_ops as op
import nfs4lib

+def opt_result(res, opt=None):
+ """Get the corresponding result at res.resarray[]"""
+ if opt == None:
+ return
+ for resa in res.resarray:
+ if resa.resop == opt:
+ return resa
+
def testSupported(t, env):
"""Do a simple RECLAIM_COMPLETE

@@ -20,3 +29,44 @@ def testSupported(t, env):
res = sess.compound([op.reclaim_complete(FALSE)])
check(res)
sess.destroy()
+
+def testReclaimAfterRECC(t, env):
+ """If client does subsequent reclaims of locking state after
+ RECLAIM_COMPLETE is done, server will return NFS4ERR_NO_GRACE.
+ rfc5661 18.51.3
+
+ FLAGS: reclaim_complete all
+ CODE: RECC2
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+
+ fname = "owner_%s" % name
+ path = sess.c.homedir + [name]
+ res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
+ check(res)
+
+ # Get stateid from OPEN4resok for making a lockowner
+ nres = opt_result(res, OP_OPEN)
+ if nres == None:
+ fail("Can not get OPEN4resok!")
+ oseqid = nres.stateid
+
+ owner = open_owner4(0, "My Open Owner")
+ otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
+ lowner = locker4(TRUE, otlowner)
+
+ # Get filehandle from GETFHresok for locking
+ nres = opt_result(res, OP_GETFH)
+ if nres == None:
+ fail("Can not get GETFHresok!")
+ cfh = nres.object
+
+ res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
+ check(res, NFS4ERR_NO_GRACE)
+ sess.destroy()
--
1.7.4.1




2011-03-03 05:56:43

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 00/17] add some test case for pynfs41

On Wed, Mar 02, 2011 at 02:23:40PM +0800, Mi Jinlong wrote:
> Add some test case for pynfs41 which according to rfc5661.

This is great, thanks!

It'll take me a little time to work through them....

--b.

2011-03-02 06:29:17

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 05/17] CLNT: test reply too big


Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_create_session.py | 30 ++++++++++++++++++++++++++++-
1 files changed, 29 insertions(+), 1 deletions(-)

diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index 1b8b119..c474ce3 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -1,6 +1,6 @@
from nfs4_const import *
import nfs4_ops as op
-from environment import check, fail
+from environment import check, fail, create_file, open_file
from nfs4_type import *
import random
import nfs4lib
@@ -427,3 +427,31 @@ def testTooSmallMaxRS(t, env):
chan_attrs, chan_attrs,
123, [])], None)
check(res, NFS4ERR_TOOSMALL)
+
+def testRepTooBig(t, env):
+ """If requester sends a request for which the size of the reply
+ would exceed ca_maxresponsesize, the replier will return
+ NFS4ERR_REP_TOO_BIG
+
+ FLAGS: create_session all
+ CODE: CSESS26
+ """
+ name = env.testname(t)
+ c1 = env.c1.new_client(name)
+ # create session with a small ca_maxresponsesize
+ chan_attrs = channel_attrs4(0,8192,50,8192,128,8,[])
+ sess1 = c1.create_session(fore_attrs=chan_attrs)
+ owner = "owner_%s" % name
+ path = sess1.c.homedir + [name]
+ res = create_file(sess1, owner, path, access=OPEN4_SHARE_ACCESS_BOTH)
+ check(res)
+
+ # write some data to file
+ fh = res.resarray[-1].object
+ stateid = res.resarray[-2].stateid
+ res = sess1.compound([op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, "write test data " * 10)])
+ check(res)
+
+ # read data rather than ca_maxresponsesize
+ res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 500)])
+ check(res, NFS4ERR_REP_TOO_BIG)
--
1.7.4.1



2011-03-02 06:31:54

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 09/17] CLNT: test Bad Sequenceid At Slot

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_sequence.py | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index ed0cc8c..4ea5cab 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -338,3 +338,28 @@ def testSessionidSequenceidSlotid(t, env):

if not nfs4lib.test_equal(res.resarray[0].sr_slotid, 2, "int"):
fail("server return bad slotid")
+
+def testBadSequenceidAtSlot(t, env):
+ """ If the difference between sa_sequenceid and the server's cached
+ sequence ID at the slot ID is two (2) or more, or if sa_sequenceid
+ is less than the cached sequence ID , server MUST return
+ NFS4ERR_SEQ_MISORDERED. rfc5661 18.46.3
+
+ FLAGS: sequence all
+ CODE: SEQ13
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION
+ sess1 = c.create_session()
+
+ sid = sess1.sessionid
+ res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
+ check(res)
+
+ seqid = res.resarray[0].sr_sequenceid
+ # SEQUENCE with bad sr_sequenceid
+ res = c.c.compound([op.sequence(sid, seqid + 2, 2, 3, True)])
+ check(res, NFS4ERR_SEQ_MISORDERED)
+
+ res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
+ check(res, NFS4ERR_SEQ_MISORDERED)
--
1.7.4.1




2011-03-02 06:29:57

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 06/17] CLNT: test reply too big to cache

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_create_session.py | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index c474ce3..ff55d10 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -455,3 +455,24 @@ def testRepTooBig(t, env):
# read data rather than ca_maxresponsesize
res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 500)])
check(res, NFS4ERR_REP_TOO_BIG)
+
+def testRepTooBigToCache(t, env):
+ """If requester sends a request for which the size of the reply
+ would exceed ca_maxresponsesize_cached, the replier will return
+ NFS4ERR_REP_TOO_BIG_TO_CACHE
+
+ FLAGS: create_session all
+ CODE: CSESS27
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION with a small ca_maxresponsesize_cached
+ chan_attrs = channel_attrs4(0,8192,8192,10,128,8,[])
+ res = c.c.compound([op.create_session(c.clientid, c.seqid, 0,
+ chan_attrs, chan_attrs,
+ 123, [])], None)
+ check(res)
+
+ # SEQUENCE with cache this
+ sid = res.resarray[0].csr_sessionid
+ res = c.c.compound([op.sequence(sid, 1, 0, 0, True)])
+ check(res, NFS4ERR_REP_TOO_BIG_TO_CACHE)
--
1.7.4.1



2011-03-02 06:27:54

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 03/17] CLNT: check the csr_sequence at CREATE_SESSION

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/nfs4client.py | 1 +
nfs4.1/server41tests/st_create_session.py | 15 +++++++++++++++
2 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index b517c27..9786bf3 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -404,6 +404,7 @@ class SendChannel(object):
class SessionRecord(object):
def __init__(self, csr, client):
self.sessionid = csr.csr_sessionid
+ self.seqid = csr.csr_sequence
self.client = client
self.c = client.c
self.cred = client.cred
diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index 1d02a50..4185aa8 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -396,3 +396,18 @@ def testNotOnlyOp(t, env):
chan_attrs, chan_attrs,
123, []), op.putrootfh()], None)
check(res, NFS4ERR_NOT_ONLY_OP)
+
+def testCsr_sequence(t, env):
+ """The corresponding result of csa_sequence is csr_sequence,
+ which MUST be equal to csa_sequence.
+
+ FLAGS: create_session all
+ CODE: CSESS24
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION
+ chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
+ csa_sequence = c.seqid
+ sess1 = c.create_session(fore_attrs=chan_attrs)
+ if not nfs4lib.test_equal(sess1.seqid, csa_sequence, "int"):
+ fail("Server returns bad csr_sequence which not equal to csa_sequence")
--
1.7.4.1




2011-03-02 06:32:28

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 10/17] CLNT: test resues slot ID

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index 4ea5cab..391fc45 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -363,3 +363,21 @@ def testBadSequenceidAtSlot(t, env):

res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
check(res, NFS4ERR_SEQ_MISORDERED)
+
+def testReuseSlotID(t, env):
+ """
+
+ FLAGS: sequence all
+ CODE: SEQ14
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION
+ sess1 = c.create_session()
+
+ sid = sess1.sessionid
+ res = c.c.compound([op.sequence(sid, 1, 2, 3, True), op.putrootfh()])
+ check(res)
+
+ res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
+ # should we also check the ERROR of NFS4ERR_SEQ_FALSE_RETRY ??
+ check(res)
--
1.7.4.1




2011-03-28 08:57:54

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH v2 2/5] CLNT: add a simple test about RECLAIM_COMPLETE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/__init__.py | 1 +
nfs4.1/server41tests/st_reclaim_complete.py | 22 ++++++++++++++++++++++
2 files changed, 23 insertions(+), 0 deletions(-)
create mode 100644 nfs4.1/server41tests/st_reclaim_complete.py

diff --git a/nfs4.1/server41tests/__init__.py b/nfs4.1/server41tests/__init__.py
index 3b4411a..1cc2048 100644
--- a/nfs4.1/server41tests/__init__.py
+++ b/nfs4.1/server41tests/__init__.py
@@ -2,6 +2,7 @@ __all__ = ["st_exchange_id.py", # draft 21
"st_compound.py",
"st_create_session.py",
"st_destroy_session.py",
+ "st_reclaim_complete.py",
"st_secinfo_no_name.py",
"st_secinfo.py",
"st_sequence.py",
diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
new file mode 100644
index 0000000..5e3174c
--- /dev/null
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -0,0 +1,22 @@
+from st_create_session import create_session
+from nfs4_const import *
+from environment import check, fail, use_obj, create_file
+import nfs4_ops as op
+import nfs4lib
+
+def testSupported(t, env):
+ """Do a simple RECLAIM_COMPLETE
+
+ FLAGS: reclaim_complete all
+ CODE: RECC1
+ """
+ c = env.c1.new_client(env.testname(t))
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.putrootfh(), op.reclaim_complete(TRUE)])
+ check(res)
+
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+ sess.destroy()
--
1.7.4.1




2011-03-14 19:24:35

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID

On Mon, Mar 14, 2011 at 02:41:44PM -0400, J. Bruce Fields wrote:
> On Fri, Mar 04, 2011 at 05:06:31PM +0800, Mi Jinlong wrote:
> > Maybe the following one is better than before.
>
> Looks good to me, thanks!

But on testing I get a failure:

SEQ14 st_sequence.testReuseSlotID : FAILURE
AttributeError: LOOKUP4res instance has no attribute
'object'

I haven't tried to figure out what's going on there.

--b.

>
> Very minor nit:
>
> > +def testReuseSlotID(t, env):
> > + """ If client reuses a slot ID and sequence ID for a completely
> > + different request, server MAY treat the request as if it is
> > + a retry of what it has already executed. rfc5661 18.46.3
> > +
> > + FLAGS: sequence all
> > + CODE: SEQ14
> > + """
> > + c = env.c1.new_client(env.testname(t))
> > + # CREATE_SESSION
> > + sess1 = c.create_session()
> > +
> > + name = "%s_1" % env.testname(t)
> > + res = create_file(sess1, name)
>
> Could you check your patches for trailing whitespace? (There's an extra
> space at the end of that line.)
>
> (No need to resend anything.)
>
> --b.
>
> > + check(res)
> > +
> > + sid = sess1.sessionid
> > + seqid = nfs4lib.inc_u32(sess1.seqid)
> > + fh = res.resarray[3].object
> > + homedir = sess1.c.homedir[0]
> > +
> > + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
> > + op.lookup(homedir), op.remove(name)])
> > + check(res)
> > +
> > + # Reuses slot ID and sequence ID for different request
> > + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
> > + op.lookup(homedir), op.rename(name, "test")])
> > + check(res)
> > --
> > 1.7.4.1
> >
> >

2011-03-15 02:46:06

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID



J. Bruce Fields:
> On Mon, Mar 14, 2011 at 02:41:44PM -0400, J. Bruce Fields wrote:
>> On Fri, Mar 04, 2011 at 05:06:31PM +0800, Mi Jinlong wrote:
>>> Maybe the following one is better than before.
>> Looks good to me, thanks!
>
> But on testing I get a failure:
>
> SEQ14 st_sequence.testReuseSlotID : FAILURE
> AttributeError: LOOKUP4res instance has no attribute
> 'object'

See below.

>
> I haven't tried to figure out what's going on there.
>
> --b.
>
>> Very minor nit:
>>
>>> +def testReuseSlotID(t, env):
>>> + """ If client reuses a slot ID and sequence ID for a completely
>>> + different request, server MAY treat the request as if it is
>>> + a retry of what it has already executed. rfc5661 18.46.3
>>> +
>>> + FLAGS: sequence all
>>> + CODE: SEQ14
>>> + """
>>> + c = env.c1.new_client(env.testname(t))
>>> + # CREATE_SESSION
>>> + sess1 = c.create_session()
>>> +
>>> + name = "%s_1" % env.testname(t)
>>> + res = create_file(sess1, name)
>> Could you check your patches for trailing whitespace? (There's an extra
>> space at the end of that line.)

I will pay attention to that in the future.

>>
>> (No need to resend anything.)
>>
>> --b.
>>
>>> + check(res)
>>> +
>>> + sid = sess1.sessionid
>>> + seqid = nfs4lib.inc_u32(sess1.seqid)
>>> + fh = res.resarray[3].object

The error only appears here.

At my machine, the res.resarray[3] is GETFHres.
As the above error message shown res.resarray[3] is LOOKUP4res.
Is it the nfs4lib's problem?

--
thanks,
Mi Jinlong

>>> + homedir = sess1.c.homedir[0]
>>> +
>>> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
>>> + op.lookup(homedir), op.remove(name)])
>>> + check(res)
>>> +
>>> + # Reuses slot ID and sequence ID for different request
>>> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
>>> + op.lookup(homedir), op.rename(name, "test")])
>>> + check(res)
>>> --
>>> 1.7.4.1
>>>
>>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>


2011-03-23 09:40:45

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID



J. Bruce Fields:
> On Tue, Mar 22, 2011 at 05:44:17PM +0800, Mi Jinlong wrote:
>> I have made a mistake about this case, we don't need the filehandle from GETFHres,
>> that is just unnecessary.
>>
>> Thanks for your point about the homedir,
>> I found a function named use_obj at nfs4lib which can solve our problem.
>>
>> After fixed, maybe the following patch is OK now.
>
> Great, thanks--applied.
>
> At this point I've applied and pushed out everything I've taken from
> you.

Thanks.

>
> So let me know what else you still have that's not in my git repo. I
> know there are the reclaim_complete tests that you're still looking
> at, but there might also be a few other odd tests that I still had
> questions about?

No. Just those tests about reclaim_complete.

Maybe I have meet some other problem about pynfs41 tests,
I will send the fixing out after I check out.

--
----
thanks
Mi Jinlong


2011-03-22 09:43:19

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID



J. Bruce Fields:
> On Tue, Mar 15, 2011 at 10:47:00AM +0800, Mi Jinlong wrote:
>>
>> J. Bruce Fields:
>>> On Mon, Mar 14, 2011 at 02:41:44PM -0400, J. Bruce Fields wrote:
>>>> On Fri, Mar 04, 2011 at 05:06:31PM +0800, Mi Jinlong wrote:
>>>>> Maybe the following one is better than before.
>>>> Looks good to me, thanks!
>>> But on testing I get a failure:
>>>
>>> SEQ14 st_sequence.testReuseSlotID : FAILURE
>>> AttributeError: LOOKUP4res instance has no attribute
>>> 'object'
>> See below.
>>
>>> I haven't tried to figure out what's going on there.
>>>
>>> --b.
>>>
>>>> Very minor nit:
>>>>
>>>>> +def testReuseSlotID(t, env):
>>>>> + """ If client reuses a slot ID and sequence ID for a completely
>>>>> + different request, server MAY treat the request as if it is
>>>>> + a retry of what it has already executed. rfc5661 18.46.3
>>>>> +
>>>>> + FLAGS: sequence all
>>>>> + CODE: SEQ14
>>>>> + """
>>>>> + c = env.c1.new_client(env.testname(t))
>>>>> + # CREATE_SESSION
>>>>> + sess1 = c.create_session()
>>>>> +
>>>>> + name = "%s_1" % env.testname(t)
>>>>> + res = create_file(sess1, name)
>>>> Could you check your patches for trailing whitespace? (There's an extra
>>>> space at the end of that line.)
>> I will pay attention to that in the future.
>>
>>>> (No need to resend anything.)
>>>>
>>>> --b.
>>>>
>>>>> + check(res)
>>>>> +
>>>>> + sid = sess1.sessionid
>>>>> + seqid = nfs4lib.inc_u32(sess1.seqid)
>>>>> + fh = res.resarray[3].object
>> The error only appears here.
>>
>> At my machine, the res.resarray[3] is GETFHres.
>> As the above error message shown res.resarray[3] is LOOKUP4res.
>> Is it the nfs4lib's problem?
>
> Oh, are you assuming that the GETFH op is always at the same position in
> the compound?
>
> You can't do that--the number of LOOKUPS required to get to the file
> depends on how deep in the server's pseudofs the file is.
>
> Note the following "homedir = " line also assumes that the pynfs tests
> are being run on /, but that's not necessarily true.

I have made a mistake about this case, we don't need the filehandle from GETFHres,
that is just unnecessary.

Thanks for your point about the homedir,
I found a function named use_obj at nfs4lib which can solve our problem.

After fixed, maybe the following patch is OK now.

---
thanks,
Mi Jinlong

>From e9faf0c2e86421012296f95ce5cd9cd3338f98a2 Mon Sep 17 00:00:00 2001
From: Mi Jinlong <[email protected]>
Date: Mon, 22 Mar 2011 19:25:23 +0800
Subject: [PATCH] CLNT: test resues slot ID

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_sequence.py | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index c11fdc9..7277290 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -363,3 +363,32 @@ def testBadSequenceidAtSlot(t, env):

res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
check(res, NFS4ERR_SEQ_MISORDERED)
+
+def testReuseSlotID(t, env):
+ """ If client reuses a slot ID and sequence ID for a completely
+ different request, server MAY treat the request as if it is
+ a retry of what it has already executed. rfc5661 18.46.3
+
+ FLAGS: sequence all
+ CODE: SEQ14
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION
+ sess1 = c.create_session()
+
+ name = "%s_1" % env.testname(t)
+ res = create_file(sess1, name)
+ check(res)
+
+ sid = sess1.sessionid
+ seqid = nfs4lib.inc_u32(sess1.seqid)
+ dir = sess1.c.homedir
+
+ res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE)] +
+ nfs4lib.use_obj(dir) + [op.remove(name)])
+ check(res)
+
+ # Reuses slot ID and sequence ID for different request
+ res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE)] +
+ nfs4lib.use_obj(dir) + [op.rename(name, "test")])
+ check(res)
--
1.7.4.1





2011-03-28 08:58:47

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH v2 4/5] CLNT: test lock before RECLAIM_COMPLETE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_reclaim_complete.py | 37 +++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index 4c9fc37..c712d0e 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -70,3 +70,40 @@ def testReclaimAfterRECC(t, env):
res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
check(res, NFS4ERR_NO_GRACE)
sess.destroy()
+
+def testLockBeforeRECC(t, env):
+ """After a client establishes a new client ID, if non-reclaim
+ locking operations are done before the RECLAIM_COMPLETE,
+ error NFS4ERR_GRACE will be returned. rfc5661 18.51.3
+
+ FLAGS: reclaim_complete all
+ CODE: RECC3
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ fname = "owner_%s" % name
+ path = sess.c.homedir + [name]
+ res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
+ check(res)
+
+ # Get stateid from OPEN4resok for making a lockowner
+ nres = opt_result(res, OP_OPEN)
+ if nres == None:
+ fail("Can not get OPEN4resok!")
+ oseqid = nres.stateid
+
+ owner = open_owner4(0, "My Open Owner")
+ otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
+ lowner = locker4(TRUE, otlowner)
+
+ # Get filehandle from GETFHresok for locking
+ nres = opt_result(res, OP_GETFH)
+ if nres == None:
+ fail("Can not get GETFHresok!")
+ cfh = nres.object
+
+ res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
+ check(res, NFS4ERR_NO_GRACE)
+ sess.destroy()
--
1.7.4.1




2011-03-02 06:35:59

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 16/17] CLNT: test double RECLAIM_COMPLETE after create session

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_reclaim_complete.py | 19 +++++++++++++++++++
1 files changed, 19 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index a94f2ad..7398d54 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -76,3 +76,22 @@ def testLockBeforeRECC(t, env):

res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
check(res, NFS4ERR_NO_GRACE)
+
+def testDoubleRECC(t, env):
+ """If RECLAIM_COMPLETE is done a second time, error
+ NFS4ERR_COMPLETE_ALREADY will be returned. rfc5661 18.51.4
+
+ FLAGS: all
+ CODE: RECC4
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+
+ # RECLAIM_COMPLETE again
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res, NFS4ERR_COMPLETE_ALREADY)
--
1.7.4.1




2011-03-22 21:48:40

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID

On Tue, Mar 22, 2011 at 05:44:17PM +0800, Mi Jinlong wrote:
> I have made a mistake about this case, we don't need the filehandle from GETFHres,
> that is just unnecessary.
>
> Thanks for your point about the homedir,
> I found a function named use_obj at nfs4lib which can solve our problem.
>
> After fixed, maybe the following patch is OK now.

Great, thanks--applied.

At this point I've applied and pushed out everything I've taken from
you.

So let me know what else you still have that's not in my git repo. I
know there are the reclaim_complete tests that you're still looking
at, but there might also be a few other odd tests that I still had
questions about?

--b.

>
> ---
> thanks,
> Mi Jinlong
>
> >From e9faf0c2e86421012296f95ce5cd9cd3338f98a2 Mon Sep 17 00:00:00 2001
> From: Mi Jinlong <[email protected]>
> Date: Mon, 22 Mar 2011 19:25:23 +0800
> Subject: [PATCH] CLNT: test resues slot ID
>
> Signed-off-by: Mi Jinlong <[email protected]>
> ---
> nfs4.1/server41tests/st_sequence.py | 29 +++++++++++++++++++++++++++++
> 1 files changed, 29 insertions(+), 0 deletions(-)
>
> diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
> index c11fdc9..7277290 100644
> --- a/nfs4.1/server41tests/st_sequence.py
> +++ b/nfs4.1/server41tests/st_sequence.py
> @@ -363,3 +363,32 @@ def testBadSequenceidAtSlot(t, env):
>
> res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
> check(res, NFS4ERR_SEQ_MISORDERED)
> +
> +def testReuseSlotID(t, env):
> + """ If client reuses a slot ID and sequence ID for a completely
> + different request, server MAY treat the request as if it is
> + a retry of what it has already executed. rfc5661 18.46.3
> +
> + FLAGS: sequence all
> + CODE: SEQ14
> + """
> + c = env.c1.new_client(env.testname(t))
> + # CREATE_SESSION
> + sess1 = c.create_session()
> +
> + name = "%s_1" % env.testname(t)
> + res = create_file(sess1, name)
> + check(res)
> +
> + sid = sess1.sessionid
> + seqid = nfs4lib.inc_u32(sess1.seqid)
> + dir = sess1.c.homedir
> +
> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE)] +
> + nfs4lib.use_obj(dir) + [op.remove(name)])
> + check(res)
> +
> + # Reuses slot ID and sequence ID for different request
> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE)] +
> + nfs4lib.use_obj(dir) + [op.rename(name, "test")])
> + check(res)
> --
> 1.7.4.1
>
>
>
>

2011-03-28 08:59:14

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH v2 5/5] CLNT: test double RECLAIM_COMPLETE after create session

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_reclaim_complete.py | 20 ++++++++++++++++++++
1 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index c712d0e..ad2178c 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -107,3 +107,23 @@ def testLockBeforeRECC(t, env):
res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
check(res, NFS4ERR_NO_GRACE)
sess.destroy()
+
+def testDoubleRECC(t, env):
+ """If RECLAIM_COMPLETE is done a second time, error
+ NFS4ERR_COMPLETE_ALREADY will be returned. rfc5661 18.51.4
+
+ FLAGS: reclaim_complete all
+ CODE: RECC4
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+
+ # RECLAIM_COMPLETE again
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res, NFS4ERR_COMPLETE_ALREADY)
+ sess.destroy()
--
1.7.4.1




2011-03-02 06:26:41

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 02/17] CLNT: test lease period of unconfirmed record


Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_exchange_id.py | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
index b5e34e6..85f3092 100644
--- a/nfs4.1/server41tests/st_exchange_id.py
+++ b/nfs4.1/server41tests/st_exchange_id.py
@@ -1,5 +1,6 @@
from nfs4_const import *
import nfs4_ops as op
+import time
from environment import check, fail
from nfs4_type import *
from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
@@ -436,3 +437,28 @@ def testNotOnlyOp(t, env):
res = c.compound([op.exchange_id(owner, 0, protect, [c.impl_id]), op.putrootfh()])
# per draft 21 18.35.3, server MUST return NFS4ERR_NOT_ONLY_OP
check(res, NFS4ERR_NOT_ONLY_OP)
+
+def testLeasePeriod(t, env):
+ """Any unconfirmed record that is not confirmed within
+ a lease period SHOULD be removed.
+
+ FLAGS: exchange_id all
+ CODE: EID9
+ """
+ c1 = env.c1.new_client("%s_1" % env.testname(t))
+ c2 = env.c1.new_client("%s_2" % env.testname(t))
+ # CREATE_SESSION
+ chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
+ time.sleep(80)
+ # Inside lease period, create_session will success.
+ res1 = c1.c.compound([op.create_session(c1.clientid, c1.seqid, 0,
+ chan_attrs, chan_attrs,
+ 123, [])], None)
+ check(res1)
+
+ time.sleep(20)
+ # After lease period, create_session will get error NFS4ERR_STALE_CLIENTID
+ res2 = c2.c.compound([op.create_session(c2.clientid, c2.seqid, 0,
+ chan_attrs, chan_attrs,
+ 123, [])], None)
+ check(res2, NFS4ERR_STALE_CLIENTID)
--
1.7.4.1



2011-03-09 01:29:44

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 02/17] CLNT: test lease period of unconfirmed record

On Thu, Mar 03, 2011 at 05:07:09PM +0800, Mi Jinlong wrote:
>
>
> J. Bruce Fields :
> > On Wed, Mar 02, 2011 at 02:27:22PM +0800, Mi Jinlong wrote:
> >> Signed-off-by: Mi Jinlong <[email protected]>
> >> ---
> >> nfs4.1/server41tests/st_exchange_id.py | 26 ++++++++++++++++++++++++++
> >> 1 files changed, 26 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
> >> index b5e34e6..85f3092 100644
> >> --- a/nfs4.1/server41tests/st_exchange_id.py
> >> +++ b/nfs4.1/server41tests/st_exchange_id.py
> >> @@ -1,5 +1,6 @@
> >> from nfs4_const import *
> >> import nfs4_ops as op
> >> +import time
> >> from environment import check, fail
> >> from nfs4_type import *
> >> from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
> >> @@ -436,3 +437,28 @@ def testNotOnlyOp(t, env):
> >> res = c.compound([op.exchange_id(owner, 0, protect, [c.impl_id]), op.putrootfh()])
> >> # per draft 21 18.35.3, server MUST return NFS4ERR_NOT_ONLY_OP
> >> check(res, NFS4ERR_NOT_ONLY_OP)
> >> +
> >> +def testLeasePeriod(t, env):
> >> + """Any unconfirmed record that is not confirmed within
> >> + a lease period SHOULD be removed.
> >> +
> >> + FLAGS: exchange_id all
> >> + CODE: EID9
> >> + """
> >> + c1 = env.c1.new_client("%s_1" % env.testname(t))
> >> + c2 = env.c1.new_client("%s_2" % env.testname(t))
> >> + # CREATE_SESSION
> >> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
> >> + time.sleep(80)
> >
> > Let's not hard-code any lease time. pynfs should do a getattr to find
> > the server's lease time, and use that as the basis for calculations
> > (we need something like the getLeaseTime in the 4.0 pynfs.)
> >
> > I actually usually set the server lease time to 15 seconds for testing,
> > just to make the tests go faster....
>
> Agree with you!
> What about the following one?

Looks fine to me.

> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
> + time.sleep(lease - 10)

I changed this to

time.sleep(min(lease-10, 1))

so it'll sill work with single-digit lease, and left it the same
otherwise.

Thanks!

--b.

> + # Inside lease period, create_session will success.
> + res1 = c1.c.compound([op.create_session(c1.clientid, c1.seqid, 0,
> + chan_attrs, chan_attrs,
> + 123, [])], None)
> + check(res1)
> +
> + time.sleep(lease + 10)
> + # After lease period, create_session will get error NFS4ERR_STALE_CLIENTID
> + res2 = c2.c.compound([op.create_session(c2.clientid, c2.seqid, 0,
> + chan_attrs, chan_attrs,
> + 123, [])], None)
> + check(res2, NFS4ERR_STALE_CLIENTID)
> --
> 1.7.4.1
>
>
>

2011-03-15 03:05:49

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 15/17] CLNT: test lock before RECLAIM_COMPLETE



J. Bruce Fields:
> On Wed, Mar 02, 2011 at 02:36:15PM +0800, Mi Jinlong wrote:
>> Signed-off-by: Mi Jinlong <[email protected]>
>
> I'm getting failures I don't understand on these reclaim complete tests
> too.

Maybe there are some problem I have missing.

If testing reclaim-complete, we should restart server's NFS service.
I think those tests about reclaim-complete need some fix.

After fixed, I will send those patch again.

--
thanks,
Mi Jinlong

>
> --b.
>
>> ---
>> nfs4.1/server41tests/st_reclaim_complete.py | 26 ++++++++++++++++++++++++++
>> 1 files changed, 26 insertions(+), 0 deletions(-)
>>
>> diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
>> index 45ac9ad..a94f2ad 100644
>> --- a/nfs4.1/server41tests/st_reclaim_complete.py
>> +++ b/nfs4.1/server41tests/st_reclaim_complete.py
>> @@ -50,3 +50,29 @@ def testReclaimAfterRECC(t, env):
>>
>> res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
>> check(res, NFS4ERR_NO_GRACE)
>> +
>> +def testLockBeforeRECC(t, env):
>> + """After a client establishes a new client ID, if non-reclaim
>> + locking operations are done before the RECLAIM_COMPLETE,
>> + error NFS4ERR_GRACE will be returned. rfc5661 18.51.3
>> +
>> + FLAGS: all
>> + CODE: RECC3
>> + """
>> + name = env.testname(t)
>> + c = env.c1.new_client(name)
>> + sess = c.create_session()
>> +
>> + fname = "owner_%s" % name
>> + path = sess.c.homedir + [name]
>> + res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
>> + check(res)
>> +
>> + oseqid = res.resarray[2].stateid
>> + cfh = res.resarray[3].object
>> + owner = open_owner4(0, "My Open Owner")
>> + otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
>> + lowner = locker4(TRUE, otlowner)
>> +
>> + res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
>> + check(res, NFS4ERR_NO_GRACE)
>> --
>> 1.7.4.1
>>
>>
>>
>


2011-03-17 22:54:59

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 15/17] CLNT: test lock before RECLAIM_COMPLETE

On Tue, Mar 15, 2011 at 11:06:38AM +0800, Mi Jinlong wrote:
>
>
> J. Bruce Fields:
> > On Wed, Mar 02, 2011 at 02:36:15PM +0800, Mi Jinlong wrote:
> >> Signed-off-by: Mi Jinlong <[email protected]>
> >
> > I'm getting failures I don't understand on these reclaim complete tests
> > too.
>
> Maybe there are some problem I have missing.
>
> If testing reclaim-complete, we should restart server's NFS service.
> I think those tests about reclaim-complete need some fix.

Probably so.

Also:

> >> + oseqid = res.resarray[2].stateid
> >> + cfh = res.resarray[3].object

This has the same problem as SEQ14, I suspect.

In general I'm nervous about grabbing results directly out of the
resarray. We shouldn't have to know so much about the structure of a
compound that some other part of the code constructed.

--b.

> >> + owner = open_owner4(0, "My Open Owner")
> >> + otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
> >> + lowner = locker4(TRUE, otlowner)
> >> +
> >> + res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
> >> + check(res, NFS4ERR_NO_GRACE)
> >> --
> >> 1.7.4.1
> >>
> >>
> >>
> >
>

2011-03-02 06:31:15

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 08/17] CLNT: test the sessionid, slotid and sequenceid for SEQUENCE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_sequence.py | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index c6a5959..ed0cc8c 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -314,3 +314,27 @@ def testOpNotInSession(t, env):
# putrootfh with out session
res = c.c.compound([op.putrootfh()])
check(res, NFS4ERR_OP_NOT_IN_SESSION)
+
+def testSessionidSequenceidSlotid(t, env):
+ """ The sr_sessionid result MUST equal sa_sessionid.
+ The sr_slotid result MUST equal sa_slotid.
+ The sr_sequenceid result MUST equal sa_sequenceid.
+ rfc5661 18.46.3
+
+ FLAGS: sequence all
+ CODE: SEQ12
+ """
+ c = env.c1.new_client(env.testname(t))
+ sess1 = c.create_session()
+
+ # SEQUENCE
+ sid = sess1.sessionid
+ res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
+ if not nfs4lib.test_equal(res.resarray[0].sr_sessionid, sid, "opaque"):
+ fail("server return bad sessionid")
+
+ if not nfs4lib.test_equal(res.resarray[0].sr_sequenceid, 1, "int"):
+ fail("server return bad sequenceid")
+
+ if not nfs4lib.test_equal(res.resarray[0].sr_slotid, 2, "int"):
+ fail("server return bad slotid")
--
1.7.4.1




2011-03-17 22:52:47

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID

On Tue, Mar 15, 2011 at 10:47:00AM +0800, Mi Jinlong wrote:
>
>
> J. Bruce Fields:
> > On Mon, Mar 14, 2011 at 02:41:44PM -0400, J. Bruce Fields wrote:
> >> On Fri, Mar 04, 2011 at 05:06:31PM +0800, Mi Jinlong wrote:
> >>> Maybe the following one is better than before.
> >> Looks good to me, thanks!
> >
> > But on testing I get a failure:
> >
> > SEQ14 st_sequence.testReuseSlotID : FAILURE
> > AttributeError: LOOKUP4res instance has no attribute
> > 'object'
>
> See below.
>
> >
> > I haven't tried to figure out what's going on there.
> >
> > --b.
> >
> >> Very minor nit:
> >>
> >>> +def testReuseSlotID(t, env):
> >>> + """ If client reuses a slot ID and sequence ID for a completely
> >>> + different request, server MAY treat the request as if it is
> >>> + a retry of what it has already executed. rfc5661 18.46.3
> >>> +
> >>> + FLAGS: sequence all
> >>> + CODE: SEQ14
> >>> + """
> >>> + c = env.c1.new_client(env.testname(t))
> >>> + # CREATE_SESSION
> >>> + sess1 = c.create_session()
> >>> +
> >>> + name = "%s_1" % env.testname(t)
> >>> + res = create_file(sess1, name)
> >> Could you check your patches for trailing whitespace? (There's an extra
> >> space at the end of that line.)
>
> I will pay attention to that in the future.
>
> >>
> >> (No need to resend anything.)
> >>
> >> --b.
> >>
> >>> + check(res)
> >>> +
> >>> + sid = sess1.sessionid
> >>> + seqid = nfs4lib.inc_u32(sess1.seqid)
> >>> + fh = res.resarray[3].object
>
> The error only appears here.
>
> At my machine, the res.resarray[3] is GETFHres.
> As the above error message shown res.resarray[3] is LOOKUP4res.
> Is it the nfs4lib's problem?

Oh, are you assuming that the GETFH op is always at the same position in
the compound?

You can't do that--the number of LOOKUPS required to get to the file
depends on how deep in the server's pseudofs the file is.

Note the following "homedir = " line also assumes that the pynfs tests
are being run on /, but that's not necessarily true.

--b.

>
> --
> thanks,
> Mi Jinlong
>
> >>> + homedir = sess1.c.homedir[0]
> >>> +
> >>> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
> >>> + op.lookup(homedir), op.remove(name)])
> >>> + check(res)
> >>> +
> >>> + # Reuses slot ID and sequence ID for different request
> >>> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
> >>> + op.lookup(homedir), op.rename(name, "test")])
> >>> + check(res)
> >>> --
> >>> 1.7.4.1
> >>>
> >>>
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
> > the body of a message to [email protected]
> > More majordomo info at http://vger.kernel.org/majordomo-info.html
> >
>

2011-03-02 06:30:36

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 07/17] CLNT: test operation not in session

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_sequence.py | 13 +++++++++++++
1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index a5e344d..c6a5959 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -301,3 +301,16 @@ def testReplayCache007(t, env):
res2 = sess1.compound(ops, seq_delta=0, cache_this=False)
check(res2, NFS4ERR_RETRY_UNCACHED_REP)

+def testOpNotInSession(t, env):
+ """Operations other than SEQUENCE, BIND_CONN_TO_SESSION, EXCHANGE_ID,
+ CREATE_SESSION, and DESTROY_SESSION, MUST NOT appear as the
+ first operation in a COMPOUND. rfc5661 18.46.3
+
+ FLAGS: sequence all
+ CODE: SEQ11
+ """
+ c = env.c1.new_client(env.testname(t))
+
+ # putrootfh with out session
+ res = c.c.compound([op.putrootfh()])
+ check(res, NFS4ERR_OP_NOT_IN_SESSION)
--
1.7.4.1




2011-03-02 06:25:19

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 01/17] CLNT: check NFS4ERR_NOT_ONLY_OP for CREATE_SESSION


Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_create_session.py | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index a213a3c..1d02a50 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -382,3 +382,17 @@ def testMaxreqs(t, env):
if nfs4lib.test_equal(sess1.fore_channel.maxrequests,
chan_attrs.ca_maxrequests, "count4"):
fail("Server allows surprisingly large fore_channel maxreqs")
+
+def testNotOnlyOp(t, env):
+ """Check for NFS4ERR_NOT_ONLY_OP
+
+ FLAGS: create_session all
+ CODE: CSESS23
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION with PUT_ROOTFH
+ chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
+ res = c.c.compound([op.create_session(c.clientid, c.seqid, 0,
+ chan_attrs, chan_attrs,
+ 123, []), op.putrootfh()], None)
+ check(res, NFS4ERR_NOT_ONLY_OP)
--
1.7.4.1




2011-03-03 14:51:10

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID

On Thu, Mar 03, 2011 at 05:11:42PM +0800, Mi Jinlong wrote:
>
>
> J. Bruce Fields:
> > On Wed, Mar 02, 2011 at 02:33:09PM +0800, Mi Jinlong wrote:
> >> Signed-off-by: Mi Jinlong <[email protected]>
> >> ---
> >> nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++++++
> >> 1 files changed, 18 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
> >> index 4ea5cab..391fc45 100644
> >> --- a/nfs4.1/server41tests/st_sequence.py
> >> +++ b/nfs4.1/server41tests/st_sequence.py
> >> @@ -363,3 +363,21 @@ def testBadSequenceidAtSlot(t, env):
> >>
> >> res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
> >> check(res, NFS4ERR_SEQ_MISORDERED)
> >> +
> >> +def testReuseSlotID(t, env):
> >> + """
> >> +
> >> + FLAGS: sequence all
> >> + CODE: SEQ14
> >> + """
> >
> > Missing description?
>
> Sorry! I will add it at next version.
>
> >
> >> + c = env.c1.new_client(env.testname(t))
> >> + # CREATE_SESSION
> >> + sess1 = c.create_session()
> >> +
> >> + sid = sess1.sessionid
> >> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True), op.putrootfh()])
> >> + check(res)
> >> +
> >> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
> >> + # should we also check the ERROR of NFS4ERR_SEQ_FALSE_RETRY ??
> >
> > As I understand it, the server isn't required to recognize false
> > retries, so I don't think we can check for that.
> >
> > The only useful thing to check for, I think, is just to send the same
> > request twice and make sure the requests match.
> >
> > Actually, best would be to do this with a non-idempotent operation. For
> > example, send SEQ+RENAME twice and make sure that both renames succeed.
> > (Whereas if the server reply cache is broken and the server attempts to
> > rename the file again, the second rename will fail with NOENT.)
>
> Yes, thanks for you advice.
> I will send a new patch tomorrow.

OK, thanks. The patches I didn't comment on look mostly fine to me;
I'll push them out to my git tree as I apply them.

--b.

2011-03-03 06:14:43

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID

On Wed, Mar 02, 2011 at 02:33:09PM +0800, Mi Jinlong wrote:
> Signed-off-by: Mi Jinlong <[email protected]>
> ---
> nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++++++
> 1 files changed, 18 insertions(+), 0 deletions(-)
>
> diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
> index 4ea5cab..391fc45 100644
> --- a/nfs4.1/server41tests/st_sequence.py
> +++ b/nfs4.1/server41tests/st_sequence.py
> @@ -363,3 +363,21 @@ def testBadSequenceidAtSlot(t, env):
>
> res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
> check(res, NFS4ERR_SEQ_MISORDERED)
> +
> +def testReuseSlotID(t, env):
> + """
> +
> + FLAGS: sequence all
> + CODE: SEQ14
> + """

Missing description?

> + c = env.c1.new_client(env.testname(t))
> + # CREATE_SESSION
> + sess1 = c.create_session()
> +
> + sid = sess1.sessionid
> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True), op.putrootfh()])
> + check(res)
> +
> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
> + # should we also check the ERROR of NFS4ERR_SEQ_FALSE_RETRY ??

As I understand it, the server isn't required to recognize false
retries, so I don't think we can check for that.

The only useful thing to check for, I think, is just to send the same
request twice and make sure the requests match.

Actually, best would be to do this with a non-idempotent operation. For
example, send SEQ+RENAME twice and make sure that both renames succeed.
(Whereas if the server reply cache is broken and the server attempts to
rename the file again, the second rename will fail with NOENT.)

--b.

> + check(res)
> --
> 1.7.4.1
>
>
>

2011-03-02 06:33:09

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 11/17] CLNT: DESTROY_SESSION not the fianl operation

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_destroy_session.py | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_destroy_session.py b/nfs4.1/server41tests/st_destroy_session.py
index a60daf1..d7be8a1 100644
--- a/nfs4.1/server41tests/st_destroy_session.py
+++ b/nfs4.1/server41tests/st_destroy_session.py
@@ -133,3 +133,19 @@ def testDestroy3(t, env):
if not recall.happened:
fail("Did not get callback")

+def testDestoryNotFinalOps(t, env):
+ """ If the COMPOUND request starts with SEQUENCE, DESTROY_SESSION
+ MUST be the final operation in the COMPOUND request.
+ rfc5661 18.37.3
+
+ FLAGS: destroy_session
+ CODE: DSESS9004
+ """
+ c = env.c1.new_client(env.testname(t))
+ sess1 = c.create_session()
+
+ sid = sess1.sessionid
+ res = c.c.compound([op.sequence(sid, 1, 2, 3, False),
+ op.destroy_session(sess1.sessionid),
+ op.putrootfh()])
+ check(res, NFS4ERR_NOT_ONLY_OP)
--
1.7.4.1



2011-03-28 08:56:46

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 1/5] CLNT: try to destroy session after test complete

When testing pynfs41, I got NFS4ERR_DELAY at some tests.
At a test case, we don't destroy the session after create.
So, this patch try to destroy session test complete.

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/nfs4client.py | 4 +++
nfs4.1/server41tests/environment.py | 1 +
nfs4.1/server41tests/st_block.py | 4 +++
nfs4.1/server41tests/st_create_session.py | 20 +++++++++++++++
nfs4.1/server41tests/st_debug.py | 6 ++++
nfs4.1/server41tests/st_destroy_session.py | 9 +++++++
nfs4.1/server41tests/st_exchange_id.py | 12 ++++++++-
nfs4.1/server41tests/st_getdevicelist.py | 11 ++++++++
nfs4.1/server41tests/st_lookup.py | 5 ++++
nfs4.1/server41tests/st_lookupp.py | 11 ++++++++
nfs4.1/server41tests/st_open.py | 10 +++++++
nfs4.1/server41tests/st_putfh.py | 8 ++++++
nfs4.1/server41tests/st_reboot.py | 1 +
nfs4.1/server41tests/st_rename.py | 36 ++++++++++++++++++++++++++++
nfs4.1/server41tests/st_secinfo.py | 2 +
nfs4.1/server41tests/st_secinfo_no_name.py | 2 +
nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++
nfs4.1/server41tests/st_trunking.py | 4 +++
nfs4.1/server41tests/st_verify.py | 1 +
19 files changed, 164 insertions(+), 1 deletions(-)

diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
index 9786bf3..0b3382e 100644
--- a/nfs4.1/nfs4client.py
+++ b/nfs4.1/nfs4client.py
@@ -495,6 +495,10 @@ class SessionRecord(object):
res.resarray = res.resarray[1:]
return res

+ def destroy(self):
+ res = self.c.compound([op.destroy_session(self.sessionid)])
+ nfs4lib.check(res)
+
## def open(self, owner, name=None, type=OPEN4_NOCREATE,
## mode=UNCHECKED4, attrs={FATTR4_MODE:0644}, verf=None,
## access=OPEN4_SHARE_ACCESS_READ,
diff --git a/nfs4.1/server41tests/environment.py b/nfs4.1/server41tests/environment.py
index b8e2508..4ce7a70 100644
--- a/nfs4.1/server41tests/environment.py
+++ b/nfs4.1/server41tests/environment.py
@@ -153,6 +153,7 @@ class Environment(testmod.Environment):
# Make sure it is empty
clean_dir(sess, self.opts.home)
sess.c.null()
+ sess.destroy()

def _maketree(self, sess):
"""Make test tree"""
diff --git a/nfs4.1/server41tests/st_block.py b/nfs4.1/server41tests/st_block.py
index 779e328..c796540 100644
--- a/nfs4.1/server41tests/st_block.py
+++ b/nfs4.1/server41tests/st_block.py
@@ -49,6 +49,7 @@ def testStateid1(t, env):
# the server increments by one the value of the "seqid" in each
# subsequent LAYOUTGET and LAYOUTRETURN response,
fail("Expected stateid.seqid==%i, got %i" % (i+2, lo_stateid.seqid))
+ sess.destroy_session()

def testStateid2(t, env):
"""Check for proper sequence handling in layout stateids.
@@ -109,6 +110,7 @@ def testStateid2(t, env):
layoutupdate4(LAYOUT4_BLOCK_VOLUME, p.get_buffer()))]
res = sess.compound(ops)
check(res)
+ sess.destroy_session()

def testEmptyCommit(t, env):
"""Check for proper handling of empty LAYOUTCOMMIT.
@@ -171,6 +173,7 @@ def testEmptyCommit(t, env):
layoutupdate4(LAYOUT4_BLOCK_VOLUME, ""))]
res = sess.compound(ops)
check(res)
+ sess.destroy_session()

def testSplitCommit(t, env):
"""Check for proper handling of disjoint LAYOUTCOMMIT.opaque
@@ -218,3 +221,4 @@ def testSplitCommit(t, env):
layoutupdate4(LAYOUT4_BLOCK_VOLUME, p.get_buffer()))]
res = sess.compound(ops)
check(res)
+ sess.destroy_session()
diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index f8f59f6..5938e83 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -25,6 +25,7 @@ def testSupported1(t, env):
"""
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
+ sess.destroy();

def testSupported2(t, env):
"""Do a CREATE_SESSION after a SEQUENCE (for same client)
@@ -44,6 +45,8 @@ def testSupported2(t, env):
# Now make sure sess2 works
res = sess2.compound([op.putrootfh()])
check(res)
+ sess1.destroy();
+ sess2.destroy();

def testSupported2b(t, env):
"""Do a CREATE_SESSION after a SEQUENCE (for different client)
@@ -64,6 +67,8 @@ def testSupported2b(t, env):
# Now make sure sess2 works
res = sess2.compound([op.putrootfh()])
check(res)
+ sess1.destroy();
+ sess2.destroy();

def testNoExchange(t, env):
"""Send CREATE_SESSION when server has no record of clientid
@@ -132,6 +137,8 @@ def testReplay1a(t, env):
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")

+ sess1.destroy();
+
def testReplay1b(t, env):
"""Replay a successful SEQUENCE:CREATE_SESSION without a preceeding SEQUENCE

@@ -156,6 +163,8 @@ def testReplay1b(t, env):
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")

+ sess1.destroy();
+
def testReplay2(t, env):
"""Replay a unsuccessful CREATE_SESSION

@@ -251,6 +260,7 @@ def testCbSecParms(t, env):

c1 = env.c1.new_client(env.testname(t))
sess1 = c1.create_session(sec=sec)
+ sess1.destroy();

def testCbSecParmsDec(t, env):
"""A decode problem was found at NFS server
@@ -267,6 +277,7 @@ def testCbSecParmsDec(t, env):

c1 = env.c1.new_client(env.testname(t))
sess1 = c1.create_session(sec=sec)
+ sess1.destroy();

def testRdmaArray0(t, env):
"""Test 0 length rdma arrays
@@ -278,6 +289,7 @@ def testRdmaArray0(t, env):
chan_attrs = channel_attrs4(0, 8192,8192,8192,128,8,[])
sess1 = c1.create_session(fore_attrs=chan_attrs,
back_attrs=chan_attrs)
+ sess1.destroy();

def testRdmaArray1(t, env):
"""Test length 1 rdma arrays
@@ -289,6 +301,7 @@ def testRdmaArray1(t, env):
chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[57])
sess1 = c1.create_session(fore_attrs=chan_attrs,
back_attrs=chan_attrs)
+ sess1.destroy();

def testRdmaArray2(t, env):
"""Test length 2 rdma arrays
@@ -351,6 +364,8 @@ def testCallbackProgram(t, env):
finally:
env.c1._check_program = orig

+ sess.destroy();
+
def testCallbackVersion(t, env):
"""Check server sends callback program with a version listed in nfs4client.py

@@ -380,6 +395,8 @@ def testCallbackVersion(t, env):
finally:
env.c1._check_version = orig

+ sess.destroy()
+
def testMaxreqs(t, env):
"""A CREATE_SESSION with maxreqs too large should return
a modified value
@@ -428,6 +445,8 @@ def testCsr_sequence(t, env):
if not nfs4lib.test_equal(sess1.seqid, csa_sequence, "int"):
fail("Server returns bad csr_sequence which not equal to csa_sequence")

+ sess1.destroy()
+
def testTooSmallMaxRS(t, env):
"""If client selects a value for ca_maxresponsesize such that
a replier on a channel could never send a response,
@@ -471,6 +490,7 @@ def testRepTooBig(t, env):
# read data rather than ca_maxresponsesize
res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 500)])
check(res, NFS4ERR_REP_TOO_BIG)
+ sess1.destroy()

def testRepTooBigToCache(t, env):
"""If requester sends a request for which the size of the reply
diff --git a/nfs4.1/server41tests/st_debug.py b/nfs4.1/server41tests/st_debug.py
index aff6842..9678192 100644
--- a/nfs4.1/server41tests/st_debug.py
+++ b/nfs4.1/server41tests/st_debug.py
@@ -30,6 +30,8 @@ def testSupported2(t, env):
# STUB - since we are not handling callback, deleg_return never gets done
print res
check(res)
+ sess1.destroy()
+ sess2.destroy()

def testReadWrite(t, env):
"""Do a simple READ and WRITE
@@ -57,6 +59,7 @@ def testReadWrite(t, env):
res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)])
print res
check(res)
+ sess1.destroy()


def testDeadlock(t, env):
@@ -86,6 +89,7 @@ def testDeadlock(t, env):
res = sess1.listen(xid)
check(res)
print res
+ sess1.destroy()

def testLayout(t, env):
"""Verify layout handling
@@ -118,6 +122,7 @@ def testLayout(t, env):
0, 0xffffffff, 0, 0xffff)]
res = sess.compound(ops)
check(res)
+ sess.destroy()

def testGetDevList(t, env):
"""Check devlist
@@ -142,3 +147,4 @@ def testGetDevList(t, env):
ops = use_obj(env.opts.path) + [op.getdevicelist(LAYOUT4_BLOCK_VOLUME, 0, 0, "")]
res = sess.compound(ops)
check(res)
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_destroy_session.py b/nfs4.1/server41tests/st_destroy_session.py
index 1feb671..74893ca 100644
--- a/nfs4.1/server41tests/st_destroy_session.py
+++ b/nfs4.1/server41tests/st_destroy_session.py
@@ -27,6 +27,7 @@ def testDestroy(t, env):
env.c1.compound([sess.seq_op()], pipe=rogue)
res = c.c.compound([op.destroy_session(sess.sessionid)], pipe=rogue)
check(res)
+ sess.destroy()

def testDestroy2(t, env):
"""
@@ -74,6 +75,9 @@ def testDestroy2(t, env):
recall.wait(100) # STUB - deal with timeout
if not recall.happened:
fail("Did not get callback")
+ sess1.destroy()
+ sess2.destroy()
+ sess3.destroy()

def testDestroy3(t, env):
"""
@@ -132,6 +136,9 @@ def testDestroy3(t, env):
recall.wait(100) # STUB - deal with timeout
if not recall.happened:
fail("Did not get callback")
+ sess1.destroy()
+ sess2.destroy()
+ sess3.destroy()

def testDestoryNotFinalOps(t, env):
""" If the COMPOUND request starts with SEQUENCE, DESTROY_SESSION
@@ -149,6 +156,7 @@ def testDestoryNotFinalOps(t, env):
op.destroy_session(sess1.sessionid),
op.putrootfh()])
check(res, NFS4ERR_NOT_ONLY_OP)
+ sess1.destroy()

def testDestoryNotSoleOps(t, env):
""" If the COMPOUND request does not start with SEQUENCE,
@@ -167,3 +175,4 @@ def testDestoryNotSoleOps(t, env):

res = c.c.compound([op.putrootfh(), op.destroy_session(sess1.sessionid)])
check(res, NFS4ERR_NOT_ONLY_OP)
+ sess1.destroy()
diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
index f3e6f84..5b3cd7e 100644
--- a/nfs4.1/server41tests/st_exchange_id.py
+++ b/nfs4.1/server41tests/st_exchange_id.py
@@ -56,7 +56,7 @@ def testSupported2(t, env):
# per draft 21 13.1, server MUST set one of these bits
if not (res.resarray[0].eir_flags & EXCHGID4_FLAG_MASK_PNFS):
fail("server did not set any EXCHGID4_FLAG_USE_* bits")
-
+ sess1.destroy()

def testSSV(t, env):
"""Do a simple EXCHANGE_ID
@@ -84,6 +84,7 @@ def testSSV(t, env):
# SET_SSV
res = sess.set_ssv('\x5a' * c.protect.context.ssv_len)
print res
+ sess.destroy()

def testNoImplId(t, env):
"""Do a simple EXCHANGE_ID w/o setting client impl_id
@@ -213,6 +214,7 @@ def testNoUpdate100(t, env):
# Check that cred1 state is destroyed
res = sess1.compound([])
check(res, NFS4ERR_BADSESSION)
+ sess1.destroy()

# Need similar tests of 100 for expired lease, existing state (IN_USE)

@@ -237,6 +239,7 @@ def testNoUpdate101(t, env):
res = sess1.compound([])
check(res, NFS4ERR_BADSESSION)
# FIXME - more checks here
+ sess1.destroy()

def testNoUpdate110(t, env):
"""
@@ -255,6 +258,7 @@ def testNoUpdate110(t, env):
# Check that cred1 state is destroyed
res = sess1.compound([])
check(res, NFS4ERR_BADSESSION)
+ sess1.destroy()

# Need similar tests of 110 for expired lease, existing state (IN_USE)

@@ -272,6 +276,7 @@ def testNoUpdate111(t, env):
if c1.clientid != c2.clientid:
fail("Expected clientid %i, got %i" % (c1.clientid, c2.clientid))
# STUB - really want to check to see if E_ID results are the same
+ sess1.destroy()

def testUpdateNonexistant(t, env):
"""Do an EXCHANGE_ID update of a non-existant record
@@ -357,6 +362,7 @@ def testUpdate100(t, env):
cred=env.cred2,
flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A,
expect=NFS4ERR_NOT_SAME)
+ sess1.destroy()

def testUpdate101(t, env):
"""
@@ -372,6 +378,7 @@ def testUpdate101(t, env):
cred=env.cred1,
flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A,
expect=NFS4ERR_NOT_SAME)
+ sess1.destroy()

def testUpdate110(t, env):
"""
@@ -387,6 +394,7 @@ def testUpdate110(t, env):
cred=env.cred2,
flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A,
expect=NFS4ERR_PERM)
+ sess1.destroy()


def testUpdate111(t, env):
@@ -406,6 +414,7 @@ def testUpdate111(t, env):
fail("Record update changed clientid from %r to %r\n" %
(c1.clientid, c2.clientid))
# STUB - want to check update occurred
+ sess1.destroy()

# Want test similar to testUpdate111, that tries to update qqc that cant update

@@ -472,3 +481,4 @@ def testLeasePeriod(t, env):
chan_attrs, chan_attrs,
123, [])], None)
check(res2, NFS4ERR_STALE_CLIENTID)
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_getdevicelist.py b/nfs4.1/server41tests/st_getdevicelist.py
index 8d53633..4ee7ab7 100644
--- a/nfs4.1/server41tests/st_getdevicelist.py
+++ b/nfs4.1/server41tests/st_getdevicelist.py
@@ -32,6 +32,7 @@ def testGetDevList(t, env):
# STUB - check block stuff
dev_list = res.resarray[-1].gdlr_deviceid_list
print dev_list
+ sess.destroy()

def testGetDevInfo(t, env):
"""Check devlist
@@ -69,6 +70,8 @@ def testGetDevInfo(t, env):
p.done()
print decode

+ sess.destroy()
+

## def xxxtestLayout(t, env):
## """Verify layout handling
@@ -140,6 +143,8 @@ def testGetLayout(t, env):
p.done()
print opaque

+ sess.destroy()
+
def testEMCGetLayout(t, env):
"""Verify layout handling

@@ -183,6 +188,8 @@ def testEMCGetLayout(t, env):
p.done()
print opaque

+ sess.destroy()
+
def testLayoutReturnFile(t, env):
"""
Return a file's layout
@@ -215,6 +222,7 @@ def testLayoutReturnFile(t, env):
layoutreturn_file4(0, 0xffffffffffffffff, layout_stateid, "")))]
res = sess.compound(ops)
check(res)
+ sess.destroy()

def testLayoutReturnFsid(t, env):
"""
@@ -247,6 +255,7 @@ def testLayoutReturnFsid(t, env):
layoutreturn4(LAYOUTRETURN4_FSID))]
res = sess.compound(ops)
check(res)
+ sess.destroy()

def testLayoutReturnAll(t, env):
"""
@@ -278,6 +287,7 @@ def testLayoutReturnAll(t, env):
layoutreturn4(LAYOUTRETURN4_ALL))]
res = sess.compound(ops)
check(res)
+ sess.destroy()

def testLayoutCommit(t, env):
"""
@@ -341,5 +351,6 @@ def testLayoutCommit(t, env):
res = sess.compound(ops)
check(res)
print res
+ sess.destroy()


diff --git a/nfs4.1/server41tests/st_lookup.py b/nfs4.1/server41tests/st_lookup.py
index 33e06b9..457bef4 100644
--- a/nfs4.1/server41tests/st_lookup.py
+++ b/nfs4.1/server41tests/st_lookup.py
@@ -12,6 +12,7 @@ def testHome(t, env):
sess1 = c1.create_session()
res = sess1.compound(env.home + [op.getfh()])
check(res)
+ sess1.destroy()

def testNoFh(t, env):
"""LOOKUP should fail with NFS4ERR_NOFILEHANDLE if no (cfh)
@@ -23,6 +24,7 @@ def testNoFh(t, env):
sess1 = c1.create_session()
res = sess1.compound([op.lookup(env.testname(t))])
check(res, NFS4ERR_NOFILEHANDLE, "LOOKUP with no <cfh>")
+ sess1.destroy()

def testNonExistent(t, env):
"""LOOKUP with non-existent components should return NFS4ERR_NOENT
@@ -36,6 +38,7 @@ def testNonExistent(t, env):
res = sess1.compound(env.home + [op.lookup(name)])
check(res, NFS4ERR_NOENT,
"LOOKUP with non-existant component '%s'" % name)
+ sess1.destroy()

def testZeroLength(t, env):
"""LOOKUP with zero length name should return NFS4ERR_INVAL
@@ -47,6 +50,7 @@ def testZeroLength(t, env):
sess1 = c1.create_session()
res = sess1.compound([op.putrootfh(), op.lookup('')])
check(res, NFS4ERR_INVAL, "LOOKUP with no zero-length component")
+ sess1.destroy()

def testLongName(t, env):
"""LOOKUP should fail with NFS4ERR_NAMETOOLONG with long filenames
@@ -58,6 +62,7 @@ def testLongName(t, env):
sess1 = c1.create_session()
res = sess1.compound([op.putrootfh(), op.lookup('abc' * 512)])
check(res, NFS4ERR_NAMETOOLONG, "LOOKUP with very long component")
+ sess1.destroy()
# STUB - if get NOENT, check fattr4_maxname
# NOTE there is NO limit on component4 length

diff --git a/nfs4.1/server41tests/st_lookupp.py b/nfs4.1/server41tests/st_lookupp.py
index 512ea6b..41941e9 100644
--- a/nfs4.1/server41tests/st_lookupp.py
+++ b/nfs4.1/server41tests/st_lookupp.py
@@ -22,6 +22,7 @@ def testLookupp(t, env):
if res.resarray[2*i+1].object != res.resarray[-(2*i+1)].object:
t.fail('LOOKUPP returned %r, expected %r' %
(res.resarray[-(2*i+1)].object, res.resarray[2*i+1].object))
+ sess1.destroy()

def testFile(t, env):
"""LOOKUPP with non-dir (cfh)
@@ -34,6 +35,7 @@ def testFile(t, env):
ops = use_obj(env.opts.usefile) + [op.lookupp()]
res = sess1.compound(ops)
check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
+ sess1.destroy()

def testFifo(t, env):
"""LOOKUPP with non-dir (cfh)
@@ -46,6 +48,7 @@ def testFifo(t, env):
ops = use_obj(env.opts.usefifo) + [op.lookupp()]
res = sess1.compound(ops)
check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
+ sess1.destroy()

def testLink(t, env):
"""LOOKUPP with non-dir (cfh)
@@ -58,6 +61,7 @@ def testLink(t, env):
ops = use_obj(env.opts.uselink) + [op.lookupp()]
res = sess1.compound(ops)
check(res, NFS4ERR_SYMLINK, "LOOKUPP with non-dir <cfh>")
+ sess1.destroy()

def testBlock(t, env):
"""LOOKUPP with non-dir (cfh)
@@ -70,6 +74,7 @@ def testBlock(t, env):
ops = use_obj(env.opts.useblock) + [op.lookupp()]
res = sess1.compound(ops)
check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
+ sess1.destroy()

def testChar(t, env):
"""LOOKUPP with non-dir (cfh)
@@ -82,6 +87,7 @@ def testChar(t, env):
ops = use_obj(env.opts.usechar) + [op.lookupp()]
res = sess1.compound(ops)
check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
+ sess1.destroy()

def testSock(t, env):
"""LOOKUPP with non-dir (cfh)
@@ -94,6 +100,7 @@ def testSock(t, env):
ops = use_obj(env.opts.usesocket) + [op.lookupp()]
res = sess1.compound(ops)
check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
+ sess1.destroy()

def testLookuppRoot(t, env):
"""Lookupp from root should return NFS4ERR_NOENT
@@ -108,6 +115,7 @@ def testLookuppRoot(t, env):
fh = res.resarray[-1].object
res = sess1.compound([op.putfh(fh), op.lookupp()])
check(res, NFS4ERR_NOENT)
+ sess1.destroy()

def testNoFH(t, env):
"""Lookup without a cfh should return NFS4ERR_NOFILEHANDLE
@@ -119,6 +127,7 @@ def testNoFH(t, env):
sess1 = c1.create_session()
res = sess1.compound([op.lookupp()])
check(res, NFS4ERR_NOFILEHANDLE)
+ sess1.destroy()

def testXdev(t, env):
"""LOOKUPP with dir on different fs
@@ -138,3 +147,5 @@ def testXdev(t, env):
fh2 = res.resarray[-1].object
if fh1 != fh2:
t.fail("file handles not equal")
+
+ sess1.destroy()
diff --git a/nfs4.1/server41tests/st_open.py b/nfs4.1/server41tests/st_open.py
index 03edf76..09b2baa 100644
--- a/nfs4.1/server41tests/st_open.py
+++ b/nfs4.1/server41tests/st_open.py
@@ -30,6 +30,7 @@ def testSupported(t, env):
# see draft-10 line 19445
# QUESTION - what does "If the server supports the new _WANT_ flags" mean?
# will the server return INVAL? NOTSUPP? or just silently ignore?
+ sess1.destroy()

def testServerStateSeqid(t, env):
"""Do multiple OPENs of a file, check that server bumps stateid.seqid
@@ -49,6 +50,7 @@ def testServerStateSeqid(t, env):
check(res)
expect(res, seqid=2)
# STUB - need to check no delegation return
+ sess1.destroy()

# Test outdate, see draft22 8.2.2
def xtestClientStateSeqid(t, env):
@@ -73,6 +75,7 @@ def xtestClientStateSeqid(t, env):
stateid = res.resarray[-2].stateid
res = sess1.compound([op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, "write test data")])
check(res, NFS4ERR_BAD_STATEID, "Using an open_stateid w/o zeroing the seqid")
+ sess1.destroy()


# Test outdated by draft15 8.8
@@ -96,6 +99,7 @@ def xtestOpenSeqid(t, env):
res = open_file(sess1, owner, path, access=OPEN4_SHARE_ACCESS_READ,
seqid=1)
check(res, NFS4ERR_INVAL, msg="Using non-zero seqid in OPEN")
+ sess1.destroy()


# Test outdated by draft15 8.8
@@ -116,6 +120,7 @@ def xtestOpenClientid(t, env):
sess1 = c1.create_session()
res = create_file(sess1, env.testname(t), clientid=c1.clientid)
check(res, NFS4ERR_INVAL, msg="Using non-zero clientid in open_owner")
+ sess1.destroy()

def testReadDeleg(t, env):
"""Test read delgation handout and return
@@ -173,6 +178,9 @@ def testReadDeleg(t, env):
print res
checklist(res, [NFS4_OK, NFS4ERR_DELAY])
print "FRED - done"
+
+ sess1.destroy()
+ sess2.destroy()



@@ -201,6 +209,7 @@ def testReadWrite(t, env):
desired = "\0"*5 + data
if res.resarray[-1].data != desired:
fail("Expected %r, got %r" % (desired, res.resarray[-1].data))
+ sess1.destroy()

def testEXCLUSIVE4AtNameAttribute(t, env):
"""If the file does exist,but the stored verifier does not match,
@@ -219,3 +228,4 @@ def testEXCLUSIVE4AtNameAttribute(t, env):
res = create_file(sess1, env.testname(t), mode=EXCLUSIVE4_1,
verifier = "Justtest")
check(res, NFS4ERR_EXIST)
+ sess1.destroy()
diff --git a/nfs4.1/server41tests/st_putfh.py b/nfs4.1/server41tests/st_putfh.py
index d7bc0be..ce7edc7 100644
--- a/nfs4.1/server41tests/st_putfh.py
+++ b/nfs4.1/server41tests/st_putfh.py
@@ -23,6 +23,7 @@ def testFile(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.usefile)
+ sess.destroy()

def testLink(t, env):
"""PUTFH followed by GETFH should end up with original fh
@@ -33,6 +34,7 @@ def testLink(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.uselink)
+ sess.destroy()

def testBlock(t, env):
"""PUTFH followed by GETFH should end up with original fh
@@ -43,6 +45,7 @@ def testBlock(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.useblock)
+ sess.destroy()

def testChar(t, env):
"""PUTFH followed by GETFH should end up with original fh
@@ -53,6 +56,7 @@ def testChar(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.usechar)
+ sess.destroy()

def testDir(t, env):
"""PUTFH followed by GETFH should end up with original fh
@@ -63,6 +67,7 @@ def testDir(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.usedir)
+ sess.destroy()

def testFifo(t, env):
"""PUTFH followed by GETFH should end up with original fh
@@ -73,6 +78,7 @@ def testFifo(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.usefifo)
+ sess.destroy()

def testSocket(t, env):
"""PUTFH followed by GETFH should end up with original fh
@@ -83,6 +89,7 @@ def testSocket(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
_try_put(t, sess, env.opts.usesocket)
+ sess.destroy()

def testBadHandle(t, env):
"""PUTFH with bad filehandle should return NFS4ERR_BADHANDLE
@@ -94,3 +101,4 @@ def testBadHandle(t, env):
sess = c.create_session()
res = sess.compound([op.putfh('abc')])
check(res, NFS4ERR_BADHANDLE, "PUTFH with bad filehandle='abc'")
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_reboot.py b/nfs4.1/server41tests/st_reboot.py
index 9eee19d..31f4b3f 100644
--- a/nfs4.1/server41tests/st_reboot.py
+++ b/nfs4.1/server41tests/st_reboot.py
@@ -74,3 +74,4 @@ def testRebootValid(t, env):
reclaim_complete(sess)
finally:
env.sleep(sleeptime, "Waiting for grace period to end")
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_rename.py b/nfs4.1/server41tests/st_rename.py
index 331cd21..554597c 100644
--- a/nfs4.1/server41tests/st_rename.py
+++ b/nfs4.1/server41tests/st_rename.py
@@ -17,6 +17,7 @@ def testValidDir(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of directory %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testValidFile(t, env):
"""RENAME : normal operation
@@ -32,6 +33,7 @@ def testValidFile(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of file %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testValidLink(t, env):
"""RENAME : normal operation
@@ -49,6 +51,7 @@ def testValidLink(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of symlink %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testValidBlock(t, env):
"""RENAME : normal operation
@@ -66,6 +69,7 @@ def testValidBlock(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of block device %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testValidChar(t, env):
"""RENAME : normal operation
@@ -83,6 +87,7 @@ def testValidChar(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of character device %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testValidFifo(t, env):
"""RENAME : normal operation
@@ -100,6 +105,7 @@ def testValidFifo(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of fifo %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testValidSocket(t, env):
"""RENAME : normal operation
@@ -117,6 +123,7 @@ def testValidSocket(t, env):
res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
check(res, msg="RENAME of socket %s/dir1/foo to %s/dir2/bar" %
(name, name))
+ sess.destroy()

def testSfhFile(t, env):
"""RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
@@ -129,6 +136,7 @@ def testSfhFile(t, env):
sess = c.create_session()
res = rename_obj(sess, env.opts.usefile + [name], env.c1.homedir + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
+ sess.destroy()

def testSfhLink(t, env):
"""RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
@@ -141,6 +149,7 @@ def testSfhLink(t, env):
sess = c.create_session()
res = rename_obj(sess, env.opts.uselink + [name], env.c1.homedir + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
+ sess.destroy()

def testSfhBlock(t, env):
"""RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
@@ -153,6 +162,7 @@ def testSfhBlock(t, env):
sess = c.create_session()
res = rename_obj(sess, env.opts.useblock + [name], env.c1.homedir + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
+ sess.destroy()

def testSfhChar(t, env):
"""RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
@@ -165,6 +175,7 @@ def testSfhChar(t, env):
sess = c.create_session()
res = rename_obj(sess, env.opts.usechar + [name], env.c1.homedir + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
+ sess.destroy()

def testSfhFifo(t, env):
"""RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
@@ -177,6 +188,7 @@ def testSfhFifo(t, env):
sess = c.create_session()
res = rename_obj(sess, env.opts.usefifo + [name], env.c1.homedir + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
+ sess.destroy()

def testSfhSocket(t, env):
"""RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
@@ -189,6 +201,7 @@ def testSfhSocket(t, env):
sess = c.create_session()
res = rename_obj(sess, env.opts.usesocket + [name], env.c1.homedir + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
+ sess.destroy()

def testCfhFile(t, env):
"""RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
@@ -203,6 +216,7 @@ def testCfhFile(t, env):
check(res)
res = rename_obj(sess, env.c1.homedir + [name], env.opts.usefile + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
+ sess.destroy()

def testCfhLink(t, env):
"""RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
@@ -217,6 +231,7 @@ def testCfhLink(t, env):
check(res)
res = rename_obj(sess, env.c1.homedir + [name], env.opts.uselink + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
+ sess.destroy()

def testCfhBlock(t, env):
"""RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
@@ -231,6 +246,7 @@ def testCfhBlock(t, env):
check(res)
res = rename_obj(sess, env.c1.homedir + [name], env.opts.useblock + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
+ sess.destroy()

def testCfhChar(t, env):
"""RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
@@ -245,6 +261,7 @@ def testCfhChar(t, env):
check(res)
res = rename_obj(sess, env.c1.homedir + [name], env.opts.usechar + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
+ sess.destroy()

def testCfhFifo(t, env):
"""RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
@@ -259,6 +276,7 @@ def testCfhFifo(t, env):
check(res)
res = rename_obj(sess, env.c1.homedir + [name], env.opts.usefifo + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
+ sess.destroy()

def testCfhSocket(t, env):
"""RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
@@ -273,6 +291,7 @@ def testCfhSocket(t, env):
check(res)
res = rename_obj(sess, env.c1.homedir + [name], env.opts.usesocket + [name])
check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
+ sess.destroy()

def testNoSfh(t, env):
"""RENAME without (sfh) should return NFS4ERR_NOFILEHANDLE
@@ -286,6 +305,7 @@ def testNoSfh(t, env):
ops = env.home + [op.rename(name, name)]
res = sess.compound(ops)
check(res, NFS4ERR_NOFILEHANDLE, "RENAME with no <sfh>")
+ sess.destroy()

# FRED - can't test No Cfh, with a Sfh

@@ -303,6 +323,7 @@ def testNonExistent(t, env):
check(res)
res = rename_obj(sess, basedir + ['foo'], basedir + ['bar'])
check(res, NFS4ERR_NOENT, "RENAME on non-existing object %s/foo" % name)
+ sess.destroy()

def testZeroLengthOldname(t, env):
"""RENAME with zero length oldname should return NFS4ERR_INVAL
@@ -318,6 +339,7 @@ def testZeroLengthOldname(t, env):
check(res)
res = rename_obj(sess, basedir + [''], basedir + ['bar'])
check(res, NFS4ERR_INVAL, "RENAME with zero length oldname")
+ sess.destroy()

def testZeroLengthNewname(t, env):
"""RENAME with zero length newname should return NFS4ERR_INVAL
@@ -333,6 +355,7 @@ def testZeroLengthNewname(t, env):
check(res)
res = rename_obj(sess, basedir + ['foo'], basedir + [''])
check(res, NFS4ERR_INVAL, "RENAME with zero length newname")
+ sess.destroy()

def testBadutf8Oldname(t, env):
"""RENAME with non-UTF8 oldname should return NFS4ERR_INVAL
@@ -350,6 +373,7 @@ def testBadutf8Oldname(t, env):
res = rename_obj(sess, basedir + [bad_utf8], basedir + [name])
check(res, NFS4ERR_INVAL, "RENAME with non-UTF8 oldname %s/%s" %
(name, repr(bad_utf8)[1:-1]))
+ sess.destroy()

def testBadutf8Newname(t, env):
"""RENAME with non-UTF8 newname should return NFS4ERR_INVAL
@@ -366,6 +390,7 @@ def testBadutf8Newname(t, env):
res = rename_obj(sess, basedir + [name], basedir + [bad_utf8])
check(res, NFS4ERR_INVAL, "RENAME with non-UTF8 newname %s/%s" %
(name, repr(bad_utf8)[1:-1]))
+ sess.destroy()

def testDotsOldname(t, env):
"""RENAME from nonexistant . or .. should return _NOENT/_BADNAME
@@ -384,6 +409,7 @@ def testDotsOldname(t, env):
res = rename_obj(sess, basedir + ['..'], basedir + [name])
check(res, NFS4ERR_BADNAME, "RENAME from nonexistant '..'",
[NFS4ERR_NOENT])
+ sess.destroy()

def testDotsNewname(t, env):
"""RENAME into . or .. should return _BADNAME or NFS4_OK
@@ -402,6 +428,7 @@ def testDotsNewname(t, env):
res = rename_obj(sess, basedir + [name], basedir + ['..'])
check(res, NFS4ERR_BADNAME, "RENAME into '..'",
[NFS4_OK])
+ sess.destroy()

def testDirToObj(t, env):
"""RENAME dir into existing nondir should return NFS4ERR_EXIST
@@ -416,6 +443,7 @@ def testDirToObj(t, env):
maketree(sess, [name, ['dir'], 'file'])
res = rename_obj(sess, basedir + ['dir'], basedir + ['file'])
check(res, NFS4ERR_EXIST, "RENAME dir into existing file")
+ sess.destroy()

def testDirToDir(t, env):
"""RENAME dir into existing, empty dir should retrun NFS4_OK
@@ -430,6 +458,7 @@ def testDirToDir(t, env):
maketree(sess, [name, ['dir1', ['foo']], ['dir2']])
res = rename_obj(sess, basedir + ['dir1'], basedir + ['dir2'])
check(res, msg="RENAME dir1 into existing, empty dir2")
+ sess.destroy()

def testFileToDir(t, env):
"""RENAME file into existing dir should return NFS4ERR_EXIST
@@ -444,6 +473,7 @@ def testFileToDir(t, env):
maketree(sess, [name, ['dir'], 'file'])
res = rename_obj(sess, basedir + ['file'], basedir + ['dir'])
check(res, NFS4ERR_EXIST, "RENAME file into existing dir")
+ sess.destroy()

def testFileToFile(t, env):
"""RENAME file into existing file should return NFS4_OK
@@ -458,6 +488,7 @@ def testFileToFile(t, env):
maketree(sess, [name, 'file1', 'file2'])
res = rename_obj(sess, basedir + ['file1'], basedir + ['file2'])
check(res, msg="RENAME file1 into existing file2")
+ sess.destroy()

def testDirToFullDir(t, env):
"""RENAME dir into existing, nonempty dir should return NFS4ERR_EXIST
@@ -472,6 +503,7 @@ def testDirToFullDir(t, env):
maketree(sess, [name, ['dir1'], ['dir2', ['foo']]])
res = rename_obj(sess, basedir + ['dir1'], basedir + ['dir2'])
check(res, NFS4ERR_EXIST, "RENAME dir1 into existing, nonempty dir2")
+ sess.destroy()

def testFileToFullDir(t, env):
"""RENAME file into existing, nonempty dir should return NFS4ERR_EXIST
@@ -486,6 +518,7 @@ def testFileToFullDir(t, env):
maketree(sess, [name, 'file', ['dir', ['foo']]])
res = rename_obj(sess, basedir + ['file'], basedir + ['dir'])
check(res, NFS4ERR_EXIST, "RENAME file into existing, nonempty dir")
+ sess.destroy()

def testSelfRenameDir(t, env):
"""RENAME that does nothing
@@ -505,6 +538,7 @@ def testSelfRenameDir(t, env):
if scinfo.before != scinfo.after or tcinfo.before != tcinfo.after:
t.fail("RENAME of dir %s into itself should do nothing, "
"but cinfo was changed" % name)
+ sess.destroy()

def testSelfRenameFile(t, env):
"""RENAME that does nothing
@@ -524,6 +558,7 @@ def testSelfRenameFile(t, env):
if scinfo.before != scinfo.after or tcinfo.before != tcinfo.after:
t.fail("RENAME of file %s into itself should do nothing, "
"but cinfo was changed" % name)
+ sess.destroy()

def testLinkRename(t, env):
"""RENAME of file into its hard link should do nothing
@@ -545,3 +580,4 @@ def testLinkRename(t, env):
if scinfo.before != scinfo.after or tcinfo.before != tcinfo.after:
t.fail("RENAME of file into its hard link should do nothing, "
"but cinfo was changed")
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_secinfo.py b/nfs4.1/server41tests/st_secinfo.py
index c0e5b71..381898d 100644
--- a/nfs4.1/server41tests/st_secinfo.py
+++ b/nfs4.1/server41tests/st_secinfo.py
@@ -29,6 +29,7 @@ def testSupported(t, env):
# Just do a simple SECINFO
res = sess.compound([op.putfh(fh), op.secinfo(name)])
check(res)
+ sess.destroy()

def testSupported2(t, env):
"""GETFH after do a SECINFO_NO_NAME or SECINFO
@@ -55,3 +56,4 @@ def testSupported2(t, env):
# GETFH after do a SECINFO should get error NFS4ERR_NOFILEHANDLE
res = sess.compound([op.putfh(fh), op.secinfo(name), op.getfh()])
check(res, NFS4ERR_NOFILEHANDLE)
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_secinfo_no_name.py b/nfs4.1/server41tests/st_secinfo_no_name.py
index 14bc410..cc2c30f 100644
--- a/nfs4.1/server41tests/st_secinfo_no_name.py
+++ b/nfs4.1/server41tests/st_secinfo_no_name.py
@@ -18,6 +18,7 @@ def testSupported(t, env):
# Do a simple SECINFO_NO_NAME
res = sess.compound([op.putrootfh(), op.secinfo_no_name(0)])
check(res)
+ sess.destroy()

def testSupported2(t, env):
"""GETFH after do a SECINFO_NO_NAME or SECINFO
@@ -33,3 +34,4 @@ def testSupported2(t, env):
res = sess.compound([op.putrootfh(), op.secinfo_no_name(0), op.getfh()])
print res
check(res, NFS4ERR_NOFILEHANDLE)
+ sess.destroy()
diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
index 7277290..9c2a756 100644
--- a/nfs4.1/server41tests/st_sequence.py
+++ b/nfs4.1/server41tests/st_sequence.py
@@ -15,6 +15,7 @@ def testSupported(t, env):
sess = c.create_session()
res = sess.compound([])
check(res)
+ sess.destroy()

def testNotFirst(t, env):
"""SEQUENCE must be first
@@ -26,6 +27,7 @@ def testNotFirst(t, env):
sess = c.create_session()
res = sess.compound([sess.seq_op()])
check(res, NFS4ERR_SEQUENCE_POS)
+ sess.destroy()

def testNotBound(t, env):
"""SEQUENCE sent on unbound connection
@@ -70,6 +72,7 @@ def testImplicitBind(t, env):
res = env.c1.compound([sess.seq_op()], pipe=rogue)
check(res)
env.c1.close(rogue)
+ sess.destroy()

def testImplicitBind4a(t, env):
"""SEQUENCE sent on unbound connection will bind it if no enforcing done
@@ -93,6 +96,7 @@ def testImplicitBind4a(t, env):
print "B4"
env.c1.close(rogue)
print "B5"
+ sess.destroy()

def xtestImplicitBind(t, env):
"""SEQUENCE sent on unbound connection will bind it if no enforcing done
@@ -122,6 +126,7 @@ def xtestImplicitBind(t, env):
res = c.compound([op.sequence(sid, seqid, 0, 0, True)], pipe=rogue)
check(res)
c.close(rogue)
+ sess.destroy()

def testBadSession(t, env):
"""SEQUENCE sent on unknown session
@@ -148,6 +153,7 @@ def testRequestTooBig(t, env):
res = sess1.compound([op.putrootfh(), op.lookup("12345"*100)])
# FIXME - NAME_TOO_BIG is valid, don't want it to be
check(res, NFS4ERR_REQ_TOO_BIG)
+ sess1.destroy()

def testTooManyOps(t, env):
"""Send a request with more ops than the session can handle
@@ -168,6 +174,7 @@ def testTooManyOps(t, env):
lots_of_ops += [op.getattr(0)]
res = sess1.compound(lots_of_ops)
check(res, NFS4ERR_TOO_MANY_OPS)
+ sess1.destroy()

def testBadSlot(t, env):
"""Send a request with a bad slot
@@ -182,6 +189,7 @@ def testBadSlot(t, env):
# Send sequence on (non-existant) slot number 8
res = env.c1.compound([op.sequence(sess1.sessionid, 1, 8, 8, True)])
check(res, NFS4ERR_BADSLOT)
+ sess1.destroy()

def testReplayCache001(t, env):
"""Send two successful idempotent compounds with same seqid
@@ -198,6 +206,7 @@ def testReplayCache001(t, env):
res1.tag = res2.tag = ""
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")
+ sess1.destroy()

def testReplayCache002(t, env):
"""Send two successful non-idempotent compounds with same seqid
@@ -218,6 +227,7 @@ def testReplayCache002(t, env):
res1.tag = res2.tag = ""
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")
+ sess1.destroy()

def testReplayCache003(t, env):
"""Send two unsuccessful idempotent compounds with same seqid
@@ -234,6 +244,7 @@ def testReplayCache003(t, env):
res1.tag = res2.tag = ""
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")
+ sess1.destroy()

def testReplayCache004(t, env):
"""Send two unsuccessful non-idempotent compounds with same seqid
@@ -251,6 +262,7 @@ def testReplayCache004(t, env):
res1.tag = res2.tag = ""
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")
+ sess1.destroy()

def testReplayCache005(t, env):
"""Send two unsupported compounds with same seqid
@@ -267,6 +279,7 @@ def testReplayCache005(t, env):
res1.tag = res2.tag = ""
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")
+ sess1.destroy()

def testReplayCache006(t, env):
"""Send two solo sequence compounds with same seqid
@@ -283,6 +296,7 @@ def testReplayCache006(t, env):
res1.tag = res2.tag = ""
if not nfs4lib.test_equal(res1, res2):
fail("Replay results not equal")
+ sess1.destroy()

def testReplayCache007(t, env):
"""Send two successful non-idempotent compounds with same seqid and False cache_this
@@ -300,6 +314,7 @@ def testReplayCache007(t, env):
check(res1, NFS4_OK)
res2 = sess1.compound(ops, seq_delta=0, cache_this=False)
check(res2, NFS4ERR_RETRY_UNCACHED_REP)
+ sess1.destroy()

def testOpNotInSession(t, env):
"""Operations other than SEQUENCE, BIND_CONN_TO_SESSION, EXCHANGE_ID,
@@ -338,6 +353,7 @@ def testSessionidSequenceidSlotid(t, env):

if not nfs4lib.test_equal(res.resarray[0].sr_slotid, 2, "int"):
fail("server return bad slotid")
+ sess1.destroy()

def testBadSequenceidAtSlot(t, env):
""" If the difference between sa_sequenceid and the server's cached
@@ -363,6 +379,7 @@ def testBadSequenceidAtSlot(t, env):

res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
check(res, NFS4ERR_SEQ_MISORDERED)
+ sess1.destroy()

def testReuseSlotID(t, env):
""" If client reuses a slot ID and sequence ID for a completely
@@ -392,3 +409,4 @@ def testReuseSlotID(t, env):
res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE)] +
nfs4lib.use_obj(dir) + [op.rename(name, "test")])
check(res)
+ sess1.destroy()
diff --git a/nfs4.1/server41tests/st_trunking.py b/nfs4.1/server41tests/st_trunking.py
index d99f80f..a0b4281 100644
--- a/nfs4.1/server41tests/st_trunking.py
+++ b/nfs4.1/server41tests/st_trunking.py
@@ -23,6 +23,8 @@ def testTwoSessions(t, env):
c = env.c1.new_client(env.testname(t))
sess = c.create_session()
sess2 = c.create_session()
+ sess.destroy()
+ sess2.destroy()


def testUseTwoSessions(t, env):
@@ -42,6 +44,8 @@ def testUseTwoSessions(t, env):
check(res)
res = sess2.compound([])
check(res)
+ sess.destroy()
+ sess2.destroy()

# create client
# create session
diff --git a/nfs4.1/server41tests/st_verify.py b/nfs4.1/server41tests/st_verify.py
index a1bc5ca..d6e62f1 100644
--- a/nfs4.1/server41tests/st_verify.py
+++ b/nfs4.1/server41tests/st_verify.py
@@ -12,6 +12,7 @@ def _try_mand(t, env, path):
ops = use_obj(path) + [op.verify(dict)] + use_obj(path)
res = sess1.compound(ops)
check(res, msg="Verifying mandatory attributes against getattr")
+ sess1.destroy()

def _try_type(env, path, type):
c = env.c1
--
1.7.4.1




2011-03-03 09:10:52

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID



J. Bruce Fields:
> On Wed, Mar 02, 2011 at 02:33:09PM +0800, Mi Jinlong wrote:
>> Signed-off-by: Mi Jinlong <[email protected]>
>> ---
>> nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++++++
>> 1 files changed, 18 insertions(+), 0 deletions(-)
>>
>> diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
>> index 4ea5cab..391fc45 100644
>> --- a/nfs4.1/server41tests/st_sequence.py
>> +++ b/nfs4.1/server41tests/st_sequence.py
>> @@ -363,3 +363,21 @@ def testBadSequenceidAtSlot(t, env):
>>
>> res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
>> check(res, NFS4ERR_SEQ_MISORDERED)
>> +
>> +def testReuseSlotID(t, env):
>> + """
>> +
>> + FLAGS: sequence all
>> + CODE: SEQ14
>> + """
>
> Missing description?

Sorry! I will add it at next version.

>
>> + c = env.c1.new_client(env.testname(t))
>> + # CREATE_SESSION
>> + sess1 = c.create_session()
>> +
>> + sid = sess1.sessionid
>> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True), op.putrootfh()])
>> + check(res)
>> +
>> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
>> + # should we also check the ERROR of NFS4ERR_SEQ_FALSE_RETRY ??
>
> As I understand it, the server isn't required to recognize false
> retries, so I don't think we can check for that.
>
> The only useful thing to check for, I think, is just to send the same
> request twice and make sure the requests match.
>
> Actually, best would be to do this with a non-idempotent operation. For
> example, send SEQ+RENAME twice and make sure that both renames succeed.
> (Whereas if the server reply cache is broken and the server attempts to
> rename the file again, the second rename will fail with NOENT.)

Yes, thanks for you advice.
I will send a new patch tomorrow.

--
----
thanks
Mi Jinlong


2011-03-02 06:35:03

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 14/17] CLNT: test reclaim after RECLAIM_COMPLETE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_reclaim_complete.py | 31 +++++++++++++++++++++++++++
1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index 1d2d815..45ac9ad 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -1,6 +1,7 @@
from st_create_session import create_session
from nfs4_const import *
from environment import check, fail, use_obj, create_file
+from nfs4_type import open_owner4, locker4, open_to_lock_owner4
import nfs4_ops as op
import nfs4lib

@@ -19,3 +20,33 @@ def testSupported(t, env):

res = sess.compound([op.putrootfh(), op.reclaim_complete(TRUE)])
check(res)
+
+def testReclaimAfterRECC(t, env):
+ """If client does subsequent reclaims of locking state after
+ RECLAIM_COMPLETE is done, server will return NFS4ERR_NO_GRACE.
+ rfc5661 18.51.3
+
+ FLAGS: all
+ CODE: RECC2
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+
+ fname = "owner_%s" % name
+ path = sess.c.homedir + [name]
+ res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
+ check(res)
+
+ oseqid = res.resarray[2].stateid
+ cfh = res.resarray[3].object
+ owner = open_owner4(0, "My Open Owner")
+ otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
+ lowner = locker4(TRUE, otlowner)
+
+ res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
+ check(res, NFS4ERR_NO_GRACE)
--
1.7.4.1




2011-03-02 06:36:32

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 17/17] CLNT: test EXCLUSIVE4_1 for different verifier

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/environment.py | 5 +++--
nfs4.1/server41tests/st_open.py | 18 ++++++++++++++++++
2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/nfs4.1/server41tests/environment.py b/nfs4.1/server41tests/environment.py
index e961082..b8e2508 100644
--- a/nfs4.1/server41tests/environment.py
+++ b/nfs4.1/server41tests/environment.py
@@ -458,13 +458,14 @@ def create_file(sess, owner, path=None, attrs={FATTR4_MODE: 0644},
else:
dir = path[:-1]
name = path[-1]
- if (mode==EXCLUSIVE4) and (verifier==None):
+ if ((mode==EXCLUSIVE4) or (mode==EXCLUSIVE4_1)) and (verifier==None):
verifier = sess.c.verifier
if not want_deleg and access & OPEN4_SHARE_ACCESS_WANT_DELEG_MASK == 0:
access |= OPEN4_SHARE_ACCESS_WANT_NO_DELEG
# Create the file
open_op = op.open(seqid, access, deny, open_owner4(clientid, owner),
- openflag4(OPEN4_CREATE, createhow4(mode, attrs, verifier)),
+ openflag4(OPEN4_CREATE, createhow4(mode, attrs, verifier,
+ creatverfattr(verifier, attrs))),
open_claim4(CLAIM_NULL, name))
return sess.compound(use_obj(dir) + [open_op, op.getfh()])

diff --git a/nfs4.1/server41tests/st_open.py b/nfs4.1/server41tests/st_open.py
index d5900db..5d8b6b2 100644
--- a/nfs4.1/server41tests/st_open.py
+++ b/nfs4.1/server41tests/st_open.py
@@ -2,6 +2,7 @@ from st_create_session import create_session
from nfs4_const import *
from environment import check, checklist, fail, create_file, open_file
from nfs4_type import open_owner4, openflag4, createhow4, open_claim4
+from nfs4_type import creatverfattr, fattr4
import nfs4_ops as op
import threading

@@ -201,3 +202,20 @@ def testReadWrite(t, env):
if res.resarray[-1].data != desired:
fail("Expected %r, got %r" % (desired, res.resarray[-1].data))

+def testEXCLUSIVE4AtNameAttribute(t, env):
+ """If the file does exist,but the stored verifier does not match,
+ then an error of NFS4ERR_EXIST is returned from server.
+ rfc5661 18.16.3
+
+ FLAGS: open all
+ CODE: OPEN6
+ """
+ c1 = env.c1.new_client(env.testname(t))
+ sess1 = c1.create_session()
+
+ res = create_file(sess1, env.testname(t), mode=EXCLUSIVE4_1)
+ check(res)
+
+ res = create_file(sess1, env.testname(t), mode=EXCLUSIVE4_1,
+ verifier = "Justtest")
+ check(res, NFS4ERR_EXIST)
--
1.7.4.1




2011-03-02 06:28:40

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 04/17] CLNT: test with ca_maxresponsesize is too small

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_create_session.py | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
index 4185aa8..1b8b119 100644
--- a/nfs4.1/server41tests/st_create_session.py
+++ b/nfs4.1/server41tests/st_create_session.py
@@ -411,3 +411,19 @@ def testCsr_sequence(t, env):
sess1 = c.create_session(fore_attrs=chan_attrs)
if not nfs4lib.test_equal(sess1.seqid, csa_sequence, "int"):
fail("Server returns bad csr_sequence which not equal to csa_sequence")
+
+def testTooSmallMaxRS(t, env):
+ """If client selects a value for ca_maxresponsesize such that
+ a replier on a channel could never send a response,
+ server SHOULD return NFS4ERR_TOOSMALL
+
+ FLAGS: create_session all
+ CODE: CSESS25
+ """
+ c = env.c1.new_client(env.testname(t))
+ # CREATE_SESSION with too small ca_maxresponsesize
+ chan_attrs = channel_attrs4(0,8192,0,8192,128,8,[])
+ res = c.c.compound([op.create_session(c.clientid, c.seqid, 0,
+ chan_attrs, chan_attrs,
+ 123, [])], None)
+ check(res, NFS4ERR_TOOSMALL)
--
1.7.4.1




2011-03-14 18:41:46

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID

On Fri, Mar 04, 2011 at 05:06:31PM +0800, Mi Jinlong wrote:
> Maybe the following one is better than before.

Looks good to me, thanks!

Very minor nit:

> +def testReuseSlotID(t, env):
> + """ If client reuses a slot ID and sequence ID for a completely
> + different request, server MAY treat the request as if it is
> + a retry of what it has already executed. rfc5661 18.46.3
> +
> + FLAGS: sequence all
> + CODE: SEQ14
> + """
> + c = env.c1.new_client(env.testname(t))
> + # CREATE_SESSION
> + sess1 = c.create_session()
> +
> + name = "%s_1" % env.testname(t)
> + res = create_file(sess1, name)

Could you check your patches for trailing whitespace? (There's an extra
space at the end of that line.)

(No need to resend anything.)

--b.

> + check(res)
> +
> + sid = sess1.sessionid
> + seqid = nfs4lib.inc_u32(sess1.seqid)
> + fh = res.resarray[3].object
> + homedir = sess1.c.homedir[0]
> +
> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
> + op.lookup(homedir), op.remove(name)])
> + check(res)
> +
> + # Reuses slot ID and sequence ID for different request
> + res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE), op.putrootfh(),
> + op.lookup(homedir), op.rename(name, "test")])
> + check(res)
> --
> 1.7.4.1
>
>

2011-03-02 06:35:33

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 15/17] CLNT: test lock before RECLAIM_COMPLETE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_reclaim_complete.py | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
index 45ac9ad..a94f2ad 100644
--- a/nfs4.1/server41tests/st_reclaim_complete.py
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -50,3 +50,29 @@ def testReclaimAfterRECC(t, env):

res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
check(res, NFS4ERR_NO_GRACE)
+
+def testLockBeforeRECC(t, env):
+ """After a client establishes a new client ID, if non-reclaim
+ locking operations are done before the RECLAIM_COMPLETE,
+ error NFS4ERR_GRACE will be returned. rfc5661 18.51.3
+
+ FLAGS: all
+ CODE: RECC3
+ """
+ name = env.testname(t)
+ c = env.c1.new_client(name)
+ sess = c.create_session()
+
+ fname = "owner_%s" % name
+ path = sess.c.homedir + [name]
+ res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
+ check(res)
+
+ oseqid = res.resarray[2].stateid
+ cfh = res.resarray[3].object
+ owner = open_owner4(0, "My Open Owner")
+ otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
+ lowner = locker4(TRUE, otlowner)
+
+ res = sess.compound([op.putfh(cfh), op.lock(READ_LT, FALSE, 0, 1, lowner)])
+ check(res, NFS4ERR_NO_GRACE)
--
1.7.4.1




2011-03-28 08:49:33

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 0/5] a pynfs41 problem and some tests about RECLAIM_COMPLETE

Fix a pynfs41 problem and some tests about RECLAIM_COMPLETE.


--
----
thanks
Mi Jinlong


2011-03-03 06:02:25

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 02/17] CLNT: test lease period of unconfirmed record

On Wed, Mar 02, 2011 at 02:27:22PM +0800, Mi Jinlong wrote:
>
> Signed-off-by: Mi Jinlong <[email protected]>
> ---
> nfs4.1/server41tests/st_exchange_id.py | 26 ++++++++++++++++++++++++++
> 1 files changed, 26 insertions(+), 0 deletions(-)
>
> diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
> index b5e34e6..85f3092 100644
> --- a/nfs4.1/server41tests/st_exchange_id.py
> +++ b/nfs4.1/server41tests/st_exchange_id.py
> @@ -1,5 +1,6 @@
> from nfs4_const import *
> import nfs4_ops as op
> +import time
> from environment import check, fail
> from nfs4_type import *
> from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
> @@ -436,3 +437,28 @@ def testNotOnlyOp(t, env):
> res = c.compound([op.exchange_id(owner, 0, protect, [c.impl_id]), op.putrootfh()])
> # per draft 21 18.35.3, server MUST return NFS4ERR_NOT_ONLY_OP
> check(res, NFS4ERR_NOT_ONLY_OP)
> +
> +def testLeasePeriod(t, env):
> + """Any unconfirmed record that is not confirmed within
> + a lease period SHOULD be removed.
> +
> + FLAGS: exchange_id all
> + CODE: EID9
> + """
> + c1 = env.c1.new_client("%s_1" % env.testname(t))
> + c2 = env.c1.new_client("%s_2" % env.testname(t))
> + # CREATE_SESSION
> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
> + time.sleep(80)

Let's not hard-code any lease time. pynfs should do a getattr to find
the server's lease time, and use that as the basis for calculations
(we need something like the getLeaseTime in the 4.0 pynfs.)

I actually usually set the server lease time to 15 seconds for testing,
just to make the tests go faster....

> + # Inside lease period, create_session will success.
> + res1 = c1.c.compound([op.create_session(c1.clientid, c1.seqid, 0,
> + chan_attrs, chan_attrs,
> + 123, [])], None)
> + check(res1)
> +
> + time.sleep(20)

Ditto.

--b.

> + # After lease period, create_session will get error NFS4ERR_STALE_CLIENTID
> + res2 = c2.c.compound([op.create_session(c2.clientid, c2.seqid, 0,
> + chan_attrs, chan_attrs,
> + 123, [])], None)
> + check(res2, NFS4ERR_STALE_CLIENTID)
> --
> 1.7.4.1
>
>

2011-03-02 06:33:48

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 12/17] CLNT: test DESTROY_SESSION not the sole operation

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/st_destroy_session.py | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/nfs4.1/server41tests/st_destroy_session.py b/nfs4.1/server41tests/st_destroy_session.py
index d7be8a1..1feb671 100644
--- a/nfs4.1/server41tests/st_destroy_session.py
+++ b/nfs4.1/server41tests/st_destroy_session.py
@@ -149,3 +149,21 @@ def testDestoryNotFinalOps(t, env):
op.destroy_session(sess1.sessionid),
op.putrootfh()])
check(res, NFS4ERR_NOT_ONLY_OP)
+
+def testDestoryNotSoleOps(t, env):
+ """ If the COMPOUND request does not start with SEQUENCE,
+ and DESTROY_SESSION is not the sole operation,
+ then server MUST return NFS4ERR_NOT_ONLY_OP. rfc5661 18.37.3
+
+ FLAGS: destroy_session
+ CODE: DSESS9005
+ """
+ c = env.c1.new_client(env.testname(t))
+ sess1 = c.create_session()
+
+ sid = sess1.sessionid
+ res = c.c.compound([op.destroy_session(sess1.sessionid), op.putrootfh()])
+ check(res, NFS4ERR_NOT_ONLY_OP)
+
+ res = c.c.compound([op.putrootfh(), op.destroy_session(sess1.sessionid)])
+ check(res, NFS4ERR_NOT_ONLY_OP)
--
1.7.4.1




2011-03-02 06:34:17

by Mi Jinlong

[permalink] [raw]
Subject: [PATCH 13/17] CLNT: add a simple test about RECLAIM_COMPLETE

Signed-off-by: Mi Jinlong <[email protected]>
---
nfs4.1/server41tests/__init__.py | 1 +
nfs4.1/server41tests/st_reclaim_complete.py | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+), 0 deletions(-)
create mode 100644 nfs4.1/server41tests/st_reclaim_complete.py

diff --git a/nfs4.1/server41tests/__init__.py b/nfs4.1/server41tests/__init__.py
index 3b4411a..1cc2048 100644
--- a/nfs4.1/server41tests/__init__.py
+++ b/nfs4.1/server41tests/__init__.py
@@ -2,6 +2,7 @@ __all__ = ["st_exchange_id.py", # draft 21
"st_compound.py",
"st_create_session.py",
"st_destroy_session.py",
+ "st_reclaim_complete.py",
"st_secinfo_no_name.py",
"st_secinfo.py",
"st_sequence.py",
diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
new file mode 100644
index 0000000..1d2d815
--- /dev/null
+++ b/nfs4.1/server41tests/st_reclaim_complete.py
@@ -0,0 +1,21 @@
+from st_create_session import create_session
+from nfs4_const import *
+from environment import check, fail, use_obj, create_file
+import nfs4_ops as op
+import nfs4lib
+
+def testSupported(t, env):
+ """Do a simple RECLAIM_COMPLETE
+
+ FLAGS: all
+ CODE: RECC1
+ """
+ c = env.c1.new_client(env.testname(t))
+ sess = c.create_session()
+
+ # RECLAIM_COMPLETE
+ res = sess.compound([op.reclaim_complete(FALSE)])
+ check(res)
+
+ res = sess.compound([op.putrootfh(), op.reclaim_complete(TRUE)])
+ check(res)
--
1.7.4.1



2011-03-04 09:05:38

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 10/17] CLNT: test resues slot ID



Mi Jinlong :
>
> J. Bruce Fields:
>> On Wed, Mar 02, 2011 at 02:33:09PM +0800, Mi Jinlong wrote:
>>> Signed-off-by: Mi Jinlong <[email protected]>
>>> ---
>>> nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++++++
>>> 1 files changed, 18 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
>>> index 4ea5cab..391fc45 100644
>>> --- a/nfs4.1/server41tests/st_sequence.py
>>> +++ b/nfs4.1/server41tests/st_sequence.py
>>> @@ -363,3 +363,21 @@ def testBadSequenceidAtSlot(t, env):
>>>
>>> res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
>>> check(res, NFS4ERR_SEQ_MISORDERED)
>>> +
>>> +def testReuseSlotID(t, env):
>>> + """
>>> +
>>> + FLAGS: sequence all
>>> + CODE: SEQ14
>>> + """
>> Missing description?
>
> Sorry! I will add it at next version.
>
>>> + c = env.c1.new_client(env.testname(t))
>>> + # CREATE_SESSION
>>> + sess1 = c.create_session()
>>> +
>>> + sid = sess1.sessionid
>>> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True), op.putrootfh()])
>>> + check(res)
>>> +
>>> + res = c.c.compound([op.sequence(sid, 1, 2, 3, True)])
>>> + # should we also check the ERROR of NFS4ERR_SEQ_FALSE_RETRY ??
>> As I understand it, the server isn't required to recognize false
>> retries, so I don't think we can check for that.
>>
>> The only useful thing to check for, I think, is just to send the same
>> request twice and make sure the requests match.
>>
>> Actually, best would be to do this with a non-idempotent operation. For
>> example, send SEQ+RENAME twice and make sure that both renames succeed.
>> (Whereas if the server reply cache is broken and the server attempts to
>> rename the file again, the second rename will fail with NOENT.)
>
> Yes, thanks for you advice.
> I will send a new patch tomorrow.

Maybe the following one is better than before.

--
thanks,
Mi Jinlong

=========================================================

2011-03-03 09:06:20

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 02/17] CLNT: test lease period of unconfirmed record



J. Bruce Fields :
> On Wed, Mar 02, 2011 at 02:27:22PM +0800, Mi Jinlong wrote:
>> Signed-off-by: Mi Jinlong <[email protected]>
>> ---
>> nfs4.1/server41tests/st_exchange_id.py | 26 ++++++++++++++++++++++++++
>> 1 files changed, 26 insertions(+), 0 deletions(-)
>>
>> diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
>> index b5e34e6..85f3092 100644
>> --- a/nfs4.1/server41tests/st_exchange_id.py
>> +++ b/nfs4.1/server41tests/st_exchange_id.py
>> @@ -1,5 +1,6 @@
>> from nfs4_const import *
>> import nfs4_ops as op
>> +import time
>> from environment import check, fail
>> from nfs4_type import *
>> from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
>> @@ -436,3 +437,28 @@ def testNotOnlyOp(t, env):
>> res = c.compound([op.exchange_id(owner, 0, protect, [c.impl_id]), op.putrootfh()])
>> # per draft 21 18.35.3, server MUST return NFS4ERR_NOT_ONLY_OP
>> check(res, NFS4ERR_NOT_ONLY_OP)
>> +
>> +def testLeasePeriod(t, env):
>> + """Any unconfirmed record that is not confirmed within
>> + a lease period SHOULD be removed.
>> +
>> + FLAGS: exchange_id all
>> + CODE: EID9
>> + """
>> + c1 = env.c1.new_client("%s_1" % env.testname(t))
>> + c2 = env.c1.new_client("%s_2" % env.testname(t))
>> + # CREATE_SESSION
>> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
>> + time.sleep(80)
>
> Let's not hard-code any lease time. pynfs should do a getattr to find
> the server's lease time, and use that as the basis for calculations
> (we need something like the getLeaseTime in the 4.0 pynfs.)
>
> I actually usually set the server lease time to 15 seconds for testing,
> just to make the tests go faster....

Agree with you!
What about the following one?

---
thanks,
Mi Jinlong

=================================

2011-03-09 01:42:57

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 02/17] CLNT: test lease period of unconfirmed record



J. Bruce Fields :
> On Thu, Mar 03, 2011 at 05:07:09PM +0800, Mi Jinlong wrote:
>>
>> J. Bruce Fields :
>>> On Wed, Mar 02, 2011 at 02:27:22PM +0800, Mi Jinlong wrote:
>>>> Signed-off-by: Mi Jinlong <[email protected]>
>>>> ---
>>>> nfs4.1/server41tests/st_exchange_id.py | 26 ++++++++++++++++++++++++++
>>>> 1 files changed, 26 insertions(+), 0 deletions(-)
>>>>
>>>> diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
>>>> index b5e34e6..85f3092 100644
>>>> --- a/nfs4.1/server41tests/st_exchange_id.py
>>>> +++ b/nfs4.1/server41tests/st_exchange_id.py
>>>> @@ -1,5 +1,6 @@
>>>> from nfs4_const import *
>>>> import nfs4_ops as op
>>>> +import time
>>>> from environment import check, fail
>>>> from nfs4_type import *
>>>> from rpc import RPCAcceptError, GARBAGE_ARGS, RPCTimeout
>>>> @@ -436,3 +437,28 @@ def testNotOnlyOp(t, env):
>>>> res = c.compound([op.exchange_id(owner, 0, protect, [c.impl_id]), op.putrootfh()])
>>>> # per draft 21 18.35.3, server MUST return NFS4ERR_NOT_ONLY_OP
>>>> check(res, NFS4ERR_NOT_ONLY_OP)
>>>> +
>>>> +def testLeasePeriod(t, env):
>>>> + """Any unconfirmed record that is not confirmed within
>>>> + a lease period SHOULD be removed.
>>>> +
>>>> + FLAGS: exchange_id all
>>>> + CODE: EID9
>>>> + """
>>>> + c1 = env.c1.new_client("%s_1" % env.testname(t))
>>>> + c2 = env.c1.new_client("%s_2" % env.testname(t))
>>>> + # CREATE_SESSION
>>>> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
>>>> + time.sleep(80)
>>> Let's not hard-code any lease time. pynfs should do a getattr to find
>>> the server's lease time, and use that as the basis for calculations
>>> (we need something like the getLeaseTime in the 4.0 pynfs.)
>>>
>>> I actually usually set the server lease time to 15 seconds for testing,
>>> just to make the tests go faster....
>> Agree with you!
>> What about the following one?
>
> Looks fine to me.
>
>> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
>> + time.sleep(lease - 10)
>
> I changed this to
>
> time.sleep(min(lease-10, 1))
>
> so it'll sill work with single-digit lease, and left it the same
> otherwise.

After testing, that's OK.

--
thanks,
Mi Jinlong


2011-03-03 05:57:03

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 01/17] CLNT: check NFS4ERR_NOT_ONLY_OP for CREATE_SESSION

On Wed, Mar 02, 2011 at 02:26:00PM +0800, Mi Jinlong wrote:
>
> Signed-off-by: Mi Jinlong <[email protected]>

Looks fine, thanks.--b.

> ---
> nfs4.1/server41tests/st_create_session.py | 14 ++++++++++++++
> 1 files changed, 14 insertions(+), 0 deletions(-)
>
> diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
> index a213a3c..1d02a50 100644
> --- a/nfs4.1/server41tests/st_create_session.py
> +++ b/nfs4.1/server41tests/st_create_session.py
> @@ -382,3 +382,17 @@ def testMaxreqs(t, env):
> if nfs4lib.test_equal(sess1.fore_channel.maxrequests,
> chan_attrs.ca_maxrequests, "count4"):
> fail("Server allows surprisingly large fore_channel maxreqs")
> +
> +def testNotOnlyOp(t, env):
> + """Check for NFS4ERR_NOT_ONLY_OP
> +
> + FLAGS: create_session all
> + CODE: CSESS23
> + """
> + c = env.c1.new_client(env.testname(t))
> + # CREATE_SESSION with PUT_ROOTFH
> + chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[])
> + res = c.c.compound([op.create_session(c.clientid, c.seqid, 0,
> + chan_attrs, chan_attrs,
> + 123, []), op.putrootfh()], None)
> + check(res, NFS4ERR_NOT_ONLY_OP)
> --
> 1.7.4.1
>
>
>

2011-04-19 15:20:15

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 1/5] CLNT: try to destroy session after test complete

On Mon, Mar 28, 2011 at 04:57:59PM +0800, Mi Jinlong wrote:
> When testing pynfs41, I got NFS4ERR_DELAY at some tests.
> At a test case, we don't destroy the session after create.
> So, this patch try to destroy session test complete.

Sounds like a good idea.

It seems a little tedious to have to do this by hand every time; could
we do some automatic cleanup at the end of the test when the variable
goes out of scope, or something like that?

--b.

>
> Signed-off-by: Mi Jinlong <[email protected]>
> ---
> nfs4.1/nfs4client.py | 4 +++
> nfs4.1/server41tests/environment.py | 1 +
> nfs4.1/server41tests/st_block.py | 4 +++
> nfs4.1/server41tests/st_create_session.py | 20 +++++++++++++++
> nfs4.1/server41tests/st_debug.py | 6 ++++
> nfs4.1/server41tests/st_destroy_session.py | 9 +++++++
> nfs4.1/server41tests/st_exchange_id.py | 12 ++++++++-
> nfs4.1/server41tests/st_getdevicelist.py | 11 ++++++++
> nfs4.1/server41tests/st_lookup.py | 5 ++++
> nfs4.1/server41tests/st_lookupp.py | 11 ++++++++
> nfs4.1/server41tests/st_open.py | 10 +++++++
> nfs4.1/server41tests/st_putfh.py | 8 ++++++
> nfs4.1/server41tests/st_reboot.py | 1 +
> nfs4.1/server41tests/st_rename.py | 36 ++++++++++++++++++++++++++++
> nfs4.1/server41tests/st_secinfo.py | 2 +
> nfs4.1/server41tests/st_secinfo_no_name.py | 2 +
> nfs4.1/server41tests/st_sequence.py | 18 ++++++++++++++
> nfs4.1/server41tests/st_trunking.py | 4 +++
> nfs4.1/server41tests/st_verify.py | 1 +
> 19 files changed, 164 insertions(+), 1 deletions(-)
>
> diff --git a/nfs4.1/nfs4client.py b/nfs4.1/nfs4client.py
> index 9786bf3..0b3382e 100644
> --- a/nfs4.1/nfs4client.py
> +++ b/nfs4.1/nfs4client.py
> @@ -495,6 +495,10 @@ class SessionRecord(object):
> res.resarray = res.resarray[1:]
> return res
>
> + def destroy(self):
> + res = self.c.compound([op.destroy_session(self.sessionid)])
> + nfs4lib.check(res)
> +
> ## def open(self, owner, name=None, type=OPEN4_NOCREATE,
> ## mode=UNCHECKED4, attrs={FATTR4_MODE:0644}, verf=None,
> ## access=OPEN4_SHARE_ACCESS_READ,
> diff --git a/nfs4.1/server41tests/environment.py b/nfs4.1/server41tests/environment.py
> index b8e2508..4ce7a70 100644
> --- a/nfs4.1/server41tests/environment.py
> +++ b/nfs4.1/server41tests/environment.py
> @@ -153,6 +153,7 @@ class Environment(testmod.Environment):
> # Make sure it is empty
> clean_dir(sess, self.opts.home)
> sess.c.null()
> + sess.destroy()
>
> def _maketree(self, sess):
> """Make test tree"""
> diff --git a/nfs4.1/server41tests/st_block.py b/nfs4.1/server41tests/st_block.py
> index 779e328..c796540 100644
> --- a/nfs4.1/server41tests/st_block.py
> +++ b/nfs4.1/server41tests/st_block.py
> @@ -49,6 +49,7 @@ def testStateid1(t, env):
> # the server increments by one the value of the "seqid" in each
> # subsequent LAYOUTGET and LAYOUTRETURN response,
> fail("Expected stateid.seqid==%i, got %i" % (i+2, lo_stateid.seqid))
> + sess.destroy_session()
>
> def testStateid2(t, env):
> """Check for proper sequence handling in layout stateids.
> @@ -109,6 +110,7 @@ def testStateid2(t, env):
> layoutupdate4(LAYOUT4_BLOCK_VOLUME, p.get_buffer()))]
> res = sess.compound(ops)
> check(res)
> + sess.destroy_session()
>
> def testEmptyCommit(t, env):
> """Check for proper handling of empty LAYOUTCOMMIT.
> @@ -171,6 +173,7 @@ def testEmptyCommit(t, env):
> layoutupdate4(LAYOUT4_BLOCK_VOLUME, ""))]
> res = sess.compound(ops)
> check(res)
> + sess.destroy_session()
>
> def testSplitCommit(t, env):
> """Check for proper handling of disjoint LAYOUTCOMMIT.opaque
> @@ -218,3 +221,4 @@ def testSplitCommit(t, env):
> layoutupdate4(LAYOUT4_BLOCK_VOLUME, p.get_buffer()))]
> res = sess.compound(ops)
> check(res)
> + sess.destroy_session()
> diff --git a/nfs4.1/server41tests/st_create_session.py b/nfs4.1/server41tests/st_create_session.py
> index f8f59f6..5938e83 100644
> --- a/nfs4.1/server41tests/st_create_session.py
> +++ b/nfs4.1/server41tests/st_create_session.py
> @@ -25,6 +25,7 @@ def testSupported1(t, env):
> """
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> + sess.destroy();
>
> def testSupported2(t, env):
> """Do a CREATE_SESSION after a SEQUENCE (for same client)
> @@ -44,6 +45,8 @@ def testSupported2(t, env):
> # Now make sure sess2 works
> res = sess2.compound([op.putrootfh()])
> check(res)
> + sess1.destroy();
> + sess2.destroy();
>
> def testSupported2b(t, env):
> """Do a CREATE_SESSION after a SEQUENCE (for different client)
> @@ -64,6 +67,8 @@ def testSupported2b(t, env):
> # Now make sure sess2 works
> res = sess2.compound([op.putrootfh()])
> check(res)
> + sess1.destroy();
> + sess2.destroy();
>
> def testNoExchange(t, env):
> """Send CREATE_SESSION when server has no record of clientid
> @@ -132,6 +137,8 @@ def testReplay1a(t, env):
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
>
> + sess1.destroy();
> +
> def testReplay1b(t, env):
> """Replay a successful SEQUENCE:CREATE_SESSION without a preceeding SEQUENCE
>
> @@ -156,6 +163,8 @@ def testReplay1b(t, env):
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
>
> + sess1.destroy();
> +
> def testReplay2(t, env):
> """Replay a unsuccessful CREATE_SESSION
>
> @@ -251,6 +260,7 @@ def testCbSecParms(t, env):
>
> c1 = env.c1.new_client(env.testname(t))
> sess1 = c1.create_session(sec=sec)
> + sess1.destroy();
>
> def testCbSecParmsDec(t, env):
> """A decode problem was found at NFS server
> @@ -267,6 +277,7 @@ def testCbSecParmsDec(t, env):
>
> c1 = env.c1.new_client(env.testname(t))
> sess1 = c1.create_session(sec=sec)
> + sess1.destroy();
>
> def testRdmaArray0(t, env):
> """Test 0 length rdma arrays
> @@ -278,6 +289,7 @@ def testRdmaArray0(t, env):
> chan_attrs = channel_attrs4(0, 8192,8192,8192,128,8,[])
> sess1 = c1.create_session(fore_attrs=chan_attrs,
> back_attrs=chan_attrs)
> + sess1.destroy();
>
> def testRdmaArray1(t, env):
> """Test length 1 rdma arrays
> @@ -289,6 +301,7 @@ def testRdmaArray1(t, env):
> chan_attrs = channel_attrs4(0,8192,8192,8192,128,8,[57])
> sess1 = c1.create_session(fore_attrs=chan_attrs,
> back_attrs=chan_attrs)
> + sess1.destroy();
>
> def testRdmaArray2(t, env):
> """Test length 2 rdma arrays
> @@ -351,6 +364,8 @@ def testCallbackProgram(t, env):
> finally:
> env.c1._check_program = orig
>
> + sess.destroy();
> +
> def testCallbackVersion(t, env):
> """Check server sends callback program with a version listed in nfs4client.py
>
> @@ -380,6 +395,8 @@ def testCallbackVersion(t, env):
> finally:
> env.c1._check_version = orig
>
> + sess.destroy()
> +
> def testMaxreqs(t, env):
> """A CREATE_SESSION with maxreqs too large should return
> a modified value
> @@ -428,6 +445,8 @@ def testCsr_sequence(t, env):
> if not nfs4lib.test_equal(sess1.seqid, csa_sequence, "int"):
> fail("Server returns bad csr_sequence which not equal to csa_sequence")
>
> + sess1.destroy()
> +
> def testTooSmallMaxRS(t, env):
> """If client selects a value for ca_maxresponsesize such that
> a replier on a channel could never send a response,
> @@ -471,6 +490,7 @@ def testRepTooBig(t, env):
> # read data rather than ca_maxresponsesize
> res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 500)])
> check(res, NFS4ERR_REP_TOO_BIG)
> + sess1.destroy()
>
> def testRepTooBigToCache(t, env):
> """If requester sends a request for which the size of the reply
> diff --git a/nfs4.1/server41tests/st_debug.py b/nfs4.1/server41tests/st_debug.py
> index aff6842..9678192 100644
> --- a/nfs4.1/server41tests/st_debug.py
> +++ b/nfs4.1/server41tests/st_debug.py
> @@ -30,6 +30,8 @@ def testSupported2(t, env):
> # STUB - since we are not handling callback, deleg_return never gets done
> print res
> check(res)
> + sess1.destroy()
> + sess2.destroy()
>
> def testReadWrite(t, env):
> """Do a simple READ and WRITE
> @@ -57,6 +59,7 @@ def testReadWrite(t, env):
> res = sess1.compound([op.putfh(fh), op.read(stateid, 0, 1000)])
> print res
> check(res)
> + sess1.destroy()
>
>
> def testDeadlock(t, env):
> @@ -86,6 +89,7 @@ def testDeadlock(t, env):
> res = sess1.listen(xid)
> check(res)
> print res
> + sess1.destroy()
>
> def testLayout(t, env):
> """Verify layout handling
> @@ -118,6 +122,7 @@ def testLayout(t, env):
> 0, 0xffffffff, 0, 0xffff)]
> res = sess.compound(ops)
> check(res)
> + sess.destroy()
>
> def testGetDevList(t, env):
> """Check devlist
> @@ -142,3 +147,4 @@ def testGetDevList(t, env):
> ops = use_obj(env.opts.path) + [op.getdevicelist(LAYOUT4_BLOCK_VOLUME, 0, 0, "")]
> res = sess.compound(ops)
> check(res)
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_destroy_session.py b/nfs4.1/server41tests/st_destroy_session.py
> index 1feb671..74893ca 100644
> --- a/nfs4.1/server41tests/st_destroy_session.py
> +++ b/nfs4.1/server41tests/st_destroy_session.py
> @@ -27,6 +27,7 @@ def testDestroy(t, env):
> env.c1.compound([sess.seq_op()], pipe=rogue)
> res = c.c.compound([op.destroy_session(sess.sessionid)], pipe=rogue)
> check(res)
> + sess.destroy()
>
> def testDestroy2(t, env):
> """
> @@ -74,6 +75,9 @@ def testDestroy2(t, env):
> recall.wait(100) # STUB - deal with timeout
> if not recall.happened:
> fail("Did not get callback")
> + sess1.destroy()
> + sess2.destroy()
> + sess3.destroy()
>
> def testDestroy3(t, env):
> """
> @@ -132,6 +136,9 @@ def testDestroy3(t, env):
> recall.wait(100) # STUB - deal with timeout
> if not recall.happened:
> fail("Did not get callback")
> + sess1.destroy()
> + sess2.destroy()
> + sess3.destroy()
>
> def testDestoryNotFinalOps(t, env):
> """ If the COMPOUND request starts with SEQUENCE, DESTROY_SESSION
> @@ -149,6 +156,7 @@ def testDestoryNotFinalOps(t, env):
> op.destroy_session(sess1.sessionid),
> op.putrootfh()])
> check(res, NFS4ERR_NOT_ONLY_OP)
> + sess1.destroy()
>
> def testDestoryNotSoleOps(t, env):
> """ If the COMPOUND request does not start with SEQUENCE,
> @@ -167,3 +175,4 @@ def testDestoryNotSoleOps(t, env):
>
> res = c.c.compound([op.putrootfh(), op.destroy_session(sess1.sessionid)])
> check(res, NFS4ERR_NOT_ONLY_OP)
> + sess1.destroy()
> diff --git a/nfs4.1/server41tests/st_exchange_id.py b/nfs4.1/server41tests/st_exchange_id.py
> index f3e6f84..5b3cd7e 100644
> --- a/nfs4.1/server41tests/st_exchange_id.py
> +++ b/nfs4.1/server41tests/st_exchange_id.py
> @@ -56,7 +56,7 @@ def testSupported2(t, env):
> # per draft 21 13.1, server MUST set one of these bits
> if not (res.resarray[0].eir_flags & EXCHGID4_FLAG_MASK_PNFS):
> fail("server did not set any EXCHGID4_FLAG_USE_* bits")
> -
> + sess1.destroy()
>
> def testSSV(t, env):
> """Do a simple EXCHANGE_ID
> @@ -84,6 +84,7 @@ def testSSV(t, env):
> # SET_SSV
> res = sess.set_ssv('\x5a' * c.protect.context.ssv_len)
> print res
> + sess.destroy()
>
> def testNoImplId(t, env):
> """Do a simple EXCHANGE_ID w/o setting client impl_id
> @@ -213,6 +214,7 @@ def testNoUpdate100(t, env):
> # Check that cred1 state is destroyed
> res = sess1.compound([])
> check(res, NFS4ERR_BADSESSION)
> + sess1.destroy()
>
> # Need similar tests of 100 for expired lease, existing state (IN_USE)
>
> @@ -237,6 +239,7 @@ def testNoUpdate101(t, env):
> res = sess1.compound([])
> check(res, NFS4ERR_BADSESSION)
> # FIXME - more checks here
> + sess1.destroy()
>
> def testNoUpdate110(t, env):
> """
> @@ -255,6 +258,7 @@ def testNoUpdate110(t, env):
> # Check that cred1 state is destroyed
> res = sess1.compound([])
> check(res, NFS4ERR_BADSESSION)
> + sess1.destroy()
>
> # Need similar tests of 110 for expired lease, existing state (IN_USE)
>
> @@ -272,6 +276,7 @@ def testNoUpdate111(t, env):
> if c1.clientid != c2.clientid:
> fail("Expected clientid %i, got %i" % (c1.clientid, c2.clientid))
> # STUB - really want to check to see if E_ID results are the same
> + sess1.destroy()
>
> def testUpdateNonexistant(t, env):
> """Do an EXCHANGE_ID update of a non-existant record
> @@ -357,6 +362,7 @@ def testUpdate100(t, env):
> cred=env.cred2,
> flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A,
> expect=NFS4ERR_NOT_SAME)
> + sess1.destroy()
>
> def testUpdate101(t, env):
> """
> @@ -372,6 +378,7 @@ def testUpdate101(t, env):
> cred=env.cred1,
> flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A,
> expect=NFS4ERR_NOT_SAME)
> + sess1.destroy()
>
> def testUpdate110(t, env):
> """
> @@ -387,6 +394,7 @@ def testUpdate110(t, env):
> cred=env.cred2,
> flags=EXCHGID4_FLAG_UPD_CONFIRMED_REC_A,
> expect=NFS4ERR_PERM)
> + sess1.destroy()
>
>
> def testUpdate111(t, env):
> @@ -406,6 +414,7 @@ def testUpdate111(t, env):
> fail("Record update changed clientid from %r to %r\n" %
> (c1.clientid, c2.clientid))
> # STUB - want to check update occurred
> + sess1.destroy()
>
> # Want test similar to testUpdate111, that tries to update qqc that cant update
>
> @@ -472,3 +481,4 @@ def testLeasePeriod(t, env):
> chan_attrs, chan_attrs,
> 123, [])], None)
> check(res2, NFS4ERR_STALE_CLIENTID)
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_getdevicelist.py b/nfs4.1/server41tests/st_getdevicelist.py
> index 8d53633..4ee7ab7 100644
> --- a/nfs4.1/server41tests/st_getdevicelist.py
> +++ b/nfs4.1/server41tests/st_getdevicelist.py
> @@ -32,6 +32,7 @@ def testGetDevList(t, env):
> # STUB - check block stuff
> dev_list = res.resarray[-1].gdlr_deviceid_list
> print dev_list
> + sess.destroy()
>
> def testGetDevInfo(t, env):
> """Check devlist
> @@ -69,6 +70,8 @@ def testGetDevInfo(t, env):
> p.done()
> print decode
>
> + sess.destroy()
> +
>
> ## def xxxtestLayout(t, env):
> ## """Verify layout handling
> @@ -140,6 +143,8 @@ def testGetLayout(t, env):
> p.done()
> print opaque
>
> + sess.destroy()
> +
> def testEMCGetLayout(t, env):
> """Verify layout handling
>
> @@ -183,6 +188,8 @@ def testEMCGetLayout(t, env):
> p.done()
> print opaque
>
> + sess.destroy()
> +
> def testLayoutReturnFile(t, env):
> """
> Return a file's layout
> @@ -215,6 +222,7 @@ def testLayoutReturnFile(t, env):
> layoutreturn_file4(0, 0xffffffffffffffff, layout_stateid, "")))]
> res = sess.compound(ops)
> check(res)
> + sess.destroy()
>
> def testLayoutReturnFsid(t, env):
> """
> @@ -247,6 +255,7 @@ def testLayoutReturnFsid(t, env):
> layoutreturn4(LAYOUTRETURN4_FSID))]
> res = sess.compound(ops)
> check(res)
> + sess.destroy()
>
> def testLayoutReturnAll(t, env):
> """
> @@ -278,6 +287,7 @@ def testLayoutReturnAll(t, env):
> layoutreturn4(LAYOUTRETURN4_ALL))]
> res = sess.compound(ops)
> check(res)
> + sess.destroy()
>
> def testLayoutCommit(t, env):
> """
> @@ -341,5 +351,6 @@ def testLayoutCommit(t, env):
> res = sess.compound(ops)
> check(res)
> print res
> + sess.destroy()
>
>
> diff --git a/nfs4.1/server41tests/st_lookup.py b/nfs4.1/server41tests/st_lookup.py
> index 33e06b9..457bef4 100644
> --- a/nfs4.1/server41tests/st_lookup.py
> +++ b/nfs4.1/server41tests/st_lookup.py
> @@ -12,6 +12,7 @@ def testHome(t, env):
> sess1 = c1.create_session()
> res = sess1.compound(env.home + [op.getfh()])
> check(res)
> + sess1.destroy()
>
> def testNoFh(t, env):
> """LOOKUP should fail with NFS4ERR_NOFILEHANDLE if no (cfh)
> @@ -23,6 +24,7 @@ def testNoFh(t, env):
> sess1 = c1.create_session()
> res = sess1.compound([op.lookup(env.testname(t))])
> check(res, NFS4ERR_NOFILEHANDLE, "LOOKUP with no <cfh>")
> + sess1.destroy()
>
> def testNonExistent(t, env):
> """LOOKUP with non-existent components should return NFS4ERR_NOENT
> @@ -36,6 +38,7 @@ def testNonExistent(t, env):
> res = sess1.compound(env.home + [op.lookup(name)])
> check(res, NFS4ERR_NOENT,
> "LOOKUP with non-existant component '%s'" % name)
> + sess1.destroy()
>
> def testZeroLength(t, env):
> """LOOKUP with zero length name should return NFS4ERR_INVAL
> @@ -47,6 +50,7 @@ def testZeroLength(t, env):
> sess1 = c1.create_session()
> res = sess1.compound([op.putrootfh(), op.lookup('')])
> check(res, NFS4ERR_INVAL, "LOOKUP with no zero-length component")
> + sess1.destroy()
>
> def testLongName(t, env):
> """LOOKUP should fail with NFS4ERR_NAMETOOLONG with long filenames
> @@ -58,6 +62,7 @@ def testLongName(t, env):
> sess1 = c1.create_session()
> res = sess1.compound([op.putrootfh(), op.lookup('abc' * 512)])
> check(res, NFS4ERR_NAMETOOLONG, "LOOKUP with very long component")
> + sess1.destroy()
> # STUB - if get NOENT, check fattr4_maxname
> # NOTE there is NO limit on component4 length
>
> diff --git a/nfs4.1/server41tests/st_lookupp.py b/nfs4.1/server41tests/st_lookupp.py
> index 512ea6b..41941e9 100644
> --- a/nfs4.1/server41tests/st_lookupp.py
> +++ b/nfs4.1/server41tests/st_lookupp.py
> @@ -22,6 +22,7 @@ def testLookupp(t, env):
> if res.resarray[2*i+1].object != res.resarray[-(2*i+1)].object:
> t.fail('LOOKUPP returned %r, expected %r' %
> (res.resarray[-(2*i+1)].object, res.resarray[2*i+1].object))
> + sess1.destroy()
>
> def testFile(t, env):
> """LOOKUPP with non-dir (cfh)
> @@ -34,6 +35,7 @@ def testFile(t, env):
> ops = use_obj(env.opts.usefile) + [op.lookupp()]
> res = sess1.compound(ops)
> check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
> + sess1.destroy()
>
> def testFifo(t, env):
> """LOOKUPP with non-dir (cfh)
> @@ -46,6 +48,7 @@ def testFifo(t, env):
> ops = use_obj(env.opts.usefifo) + [op.lookupp()]
> res = sess1.compound(ops)
> check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
> + sess1.destroy()
>
> def testLink(t, env):
> """LOOKUPP with non-dir (cfh)
> @@ -58,6 +61,7 @@ def testLink(t, env):
> ops = use_obj(env.opts.uselink) + [op.lookupp()]
> res = sess1.compound(ops)
> check(res, NFS4ERR_SYMLINK, "LOOKUPP with non-dir <cfh>")
> + sess1.destroy()
>
> def testBlock(t, env):
> """LOOKUPP with non-dir (cfh)
> @@ -70,6 +74,7 @@ def testBlock(t, env):
> ops = use_obj(env.opts.useblock) + [op.lookupp()]
> res = sess1.compound(ops)
> check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
> + sess1.destroy()
>
> def testChar(t, env):
> """LOOKUPP with non-dir (cfh)
> @@ -82,6 +87,7 @@ def testChar(t, env):
> ops = use_obj(env.opts.usechar) + [op.lookupp()]
> res = sess1.compound(ops)
> check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
> + sess1.destroy()
>
> def testSock(t, env):
> """LOOKUPP with non-dir (cfh)
> @@ -94,6 +100,7 @@ def testSock(t, env):
> ops = use_obj(env.opts.usesocket) + [op.lookupp()]
> res = sess1.compound(ops)
> check(res, NFS4ERR_NOTDIR, "LOOKUPP with non-dir <cfh>")
> + sess1.destroy()
>
> def testLookuppRoot(t, env):
> """Lookupp from root should return NFS4ERR_NOENT
> @@ -108,6 +115,7 @@ def testLookuppRoot(t, env):
> fh = res.resarray[-1].object
> res = sess1.compound([op.putfh(fh), op.lookupp()])
> check(res, NFS4ERR_NOENT)
> + sess1.destroy()
>
> def testNoFH(t, env):
> """Lookup without a cfh should return NFS4ERR_NOFILEHANDLE
> @@ -119,6 +127,7 @@ def testNoFH(t, env):
> sess1 = c1.create_session()
> res = sess1.compound([op.lookupp()])
> check(res, NFS4ERR_NOFILEHANDLE)
> + sess1.destroy()
>
> def testXdev(t, env):
> """LOOKUPP with dir on different fs
> @@ -138,3 +147,5 @@ def testXdev(t, env):
> fh2 = res.resarray[-1].object
> if fh1 != fh2:
> t.fail("file handles not equal")
> +
> + sess1.destroy()
> diff --git a/nfs4.1/server41tests/st_open.py b/nfs4.1/server41tests/st_open.py
> index 03edf76..09b2baa 100644
> --- a/nfs4.1/server41tests/st_open.py
> +++ b/nfs4.1/server41tests/st_open.py
> @@ -30,6 +30,7 @@ def testSupported(t, env):
> # see draft-10 line 19445
> # QUESTION - what does "If the server supports the new _WANT_ flags" mean?
> # will the server return INVAL? NOTSUPP? or just silently ignore?
> + sess1.destroy()
>
> def testServerStateSeqid(t, env):
> """Do multiple OPENs of a file, check that server bumps stateid.seqid
> @@ -49,6 +50,7 @@ def testServerStateSeqid(t, env):
> check(res)
> expect(res, seqid=2)
> # STUB - need to check no delegation return
> + sess1.destroy()
>
> # Test outdate, see draft22 8.2.2
> def xtestClientStateSeqid(t, env):
> @@ -73,6 +75,7 @@ def xtestClientStateSeqid(t, env):
> stateid = res.resarray[-2].stateid
> res = sess1.compound([op.putfh(fh), op.write(stateid, 5, FILE_SYNC4, "write test data")])
> check(res, NFS4ERR_BAD_STATEID, "Using an open_stateid w/o zeroing the seqid")
> + sess1.destroy()
>
>
> # Test outdated by draft15 8.8
> @@ -96,6 +99,7 @@ def xtestOpenSeqid(t, env):
> res = open_file(sess1, owner, path, access=OPEN4_SHARE_ACCESS_READ,
> seqid=1)
> check(res, NFS4ERR_INVAL, msg="Using non-zero seqid in OPEN")
> + sess1.destroy()
>
>
> # Test outdated by draft15 8.8
> @@ -116,6 +120,7 @@ def xtestOpenClientid(t, env):
> sess1 = c1.create_session()
> res = create_file(sess1, env.testname(t), clientid=c1.clientid)
> check(res, NFS4ERR_INVAL, msg="Using non-zero clientid in open_owner")
> + sess1.destroy()
>
> def testReadDeleg(t, env):
> """Test read delgation handout and return
> @@ -173,6 +178,9 @@ def testReadDeleg(t, env):
> print res
> checklist(res, [NFS4_OK, NFS4ERR_DELAY])
> print "FRED - done"
> +
> + sess1.destroy()
> + sess2.destroy()
>
>
>
> @@ -201,6 +209,7 @@ def testReadWrite(t, env):
> desired = "\0"*5 + data
> if res.resarray[-1].data != desired:
> fail("Expected %r, got %r" % (desired, res.resarray[-1].data))
> + sess1.destroy()
>
> def testEXCLUSIVE4AtNameAttribute(t, env):
> """If the file does exist,but the stored verifier does not match,
> @@ -219,3 +228,4 @@ def testEXCLUSIVE4AtNameAttribute(t, env):
> res = create_file(sess1, env.testname(t), mode=EXCLUSIVE4_1,
> verifier = "Justtest")
> check(res, NFS4ERR_EXIST)
> + sess1.destroy()
> diff --git a/nfs4.1/server41tests/st_putfh.py b/nfs4.1/server41tests/st_putfh.py
> index d7bc0be..ce7edc7 100644
> --- a/nfs4.1/server41tests/st_putfh.py
> +++ b/nfs4.1/server41tests/st_putfh.py
> @@ -23,6 +23,7 @@ def testFile(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.usefile)
> + sess.destroy()
>
> def testLink(t, env):
> """PUTFH followed by GETFH should end up with original fh
> @@ -33,6 +34,7 @@ def testLink(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.uselink)
> + sess.destroy()
>
> def testBlock(t, env):
> """PUTFH followed by GETFH should end up with original fh
> @@ -43,6 +45,7 @@ def testBlock(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.useblock)
> + sess.destroy()
>
> def testChar(t, env):
> """PUTFH followed by GETFH should end up with original fh
> @@ -53,6 +56,7 @@ def testChar(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.usechar)
> + sess.destroy()
>
> def testDir(t, env):
> """PUTFH followed by GETFH should end up with original fh
> @@ -63,6 +67,7 @@ def testDir(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.usedir)
> + sess.destroy()
>
> def testFifo(t, env):
> """PUTFH followed by GETFH should end up with original fh
> @@ -73,6 +78,7 @@ def testFifo(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.usefifo)
> + sess.destroy()
>
> def testSocket(t, env):
> """PUTFH followed by GETFH should end up with original fh
> @@ -83,6 +89,7 @@ def testSocket(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> _try_put(t, sess, env.opts.usesocket)
> + sess.destroy()
>
> def testBadHandle(t, env):
> """PUTFH with bad filehandle should return NFS4ERR_BADHANDLE
> @@ -94,3 +101,4 @@ def testBadHandle(t, env):
> sess = c.create_session()
> res = sess.compound([op.putfh('abc')])
> check(res, NFS4ERR_BADHANDLE, "PUTFH with bad filehandle='abc'")
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_reboot.py b/nfs4.1/server41tests/st_reboot.py
> index 9eee19d..31f4b3f 100644
> --- a/nfs4.1/server41tests/st_reboot.py
> +++ b/nfs4.1/server41tests/st_reboot.py
> @@ -74,3 +74,4 @@ def testRebootValid(t, env):
> reclaim_complete(sess)
> finally:
> env.sleep(sleeptime, "Waiting for grace period to end")
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_rename.py b/nfs4.1/server41tests/st_rename.py
> index 331cd21..554597c 100644
> --- a/nfs4.1/server41tests/st_rename.py
> +++ b/nfs4.1/server41tests/st_rename.py
> @@ -17,6 +17,7 @@ def testValidDir(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of directory %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testValidFile(t, env):
> """RENAME : normal operation
> @@ -32,6 +33,7 @@ def testValidFile(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of file %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testValidLink(t, env):
> """RENAME : normal operation
> @@ -49,6 +51,7 @@ def testValidLink(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of symlink %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testValidBlock(t, env):
> """RENAME : normal operation
> @@ -66,6 +69,7 @@ def testValidBlock(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of block device %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testValidChar(t, env):
> """RENAME : normal operation
> @@ -83,6 +87,7 @@ def testValidChar(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of character device %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testValidFifo(t, env):
> """RENAME : normal operation
> @@ -100,6 +105,7 @@ def testValidFifo(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of fifo %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testValidSocket(t, env):
> """RENAME : normal operation
> @@ -117,6 +123,7 @@ def testValidSocket(t, env):
> res = rename_obj(sess, basedir + ['dir1', 'foo'], basedir + ['dir2', 'bar'])
> check(res, msg="RENAME of socket %s/dir1/foo to %s/dir2/bar" %
> (name, name))
> + sess.destroy()
>
> def testSfhFile(t, env):
> """RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
> @@ -129,6 +136,7 @@ def testSfhFile(t, env):
> sess = c.create_session()
> res = rename_obj(sess, env.opts.usefile + [name], env.c1.homedir + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
> + sess.destroy()
>
> def testSfhLink(t, env):
> """RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
> @@ -141,6 +149,7 @@ def testSfhLink(t, env):
> sess = c.create_session()
> res = rename_obj(sess, env.opts.uselink + [name], env.c1.homedir + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
> + sess.destroy()
>
> def testSfhBlock(t, env):
> """RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
> @@ -153,6 +162,7 @@ def testSfhBlock(t, env):
> sess = c.create_session()
> res = rename_obj(sess, env.opts.useblock + [name], env.c1.homedir + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
> + sess.destroy()
>
> def testSfhChar(t, env):
> """RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
> @@ -165,6 +175,7 @@ def testSfhChar(t, env):
> sess = c.create_session()
> res = rename_obj(sess, env.opts.usechar + [name], env.c1.homedir + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
> + sess.destroy()
>
> def testSfhFifo(t, env):
> """RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
> @@ -177,6 +188,7 @@ def testSfhFifo(t, env):
> sess = c.create_session()
> res = rename_obj(sess, env.opts.usefifo + [name], env.c1.homedir + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
> + sess.destroy()
>
> def testSfhSocket(t, env):
> """RENAME with non-dir (sfh) should return NFS4ERR_NOTDIR
> @@ -189,6 +201,7 @@ def testSfhSocket(t, env):
> sess = c.create_session()
> res = rename_obj(sess, env.opts.usesocket + [name], env.c1.homedir + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <sfh>")
> + sess.destroy()
>
> def testCfhFile(t, env):
> """RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
> @@ -203,6 +216,7 @@ def testCfhFile(t, env):
> check(res)
> res = rename_obj(sess, env.c1.homedir + [name], env.opts.usefile + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
> + sess.destroy()
>
> def testCfhLink(t, env):
> """RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
> @@ -217,6 +231,7 @@ def testCfhLink(t, env):
> check(res)
> res = rename_obj(sess, env.c1.homedir + [name], env.opts.uselink + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
> + sess.destroy()
>
> def testCfhBlock(t, env):
> """RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
> @@ -231,6 +246,7 @@ def testCfhBlock(t, env):
> check(res)
> res = rename_obj(sess, env.c1.homedir + [name], env.opts.useblock + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
> + sess.destroy()
>
> def testCfhChar(t, env):
> """RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
> @@ -245,6 +261,7 @@ def testCfhChar(t, env):
> check(res)
> res = rename_obj(sess, env.c1.homedir + [name], env.opts.usechar + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
> + sess.destroy()
>
> def testCfhFifo(t, env):
> """RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
> @@ -259,6 +276,7 @@ def testCfhFifo(t, env):
> check(res)
> res = rename_obj(sess, env.c1.homedir + [name], env.opts.usefifo + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
> + sess.destroy()
>
> def testCfhSocket(t, env):
> """RENAME with non-dir (cfh) should return NFS4ERR_NOTDIR
> @@ -273,6 +291,7 @@ def testCfhSocket(t, env):
> check(res)
> res = rename_obj(sess, env.c1.homedir + [name], env.opts.usesocket + [name])
> check(res, NFS4ERR_NOTDIR, "RENAME with non-dir <cfh>")
> + sess.destroy()
>
> def testNoSfh(t, env):
> """RENAME without (sfh) should return NFS4ERR_NOFILEHANDLE
> @@ -286,6 +305,7 @@ def testNoSfh(t, env):
> ops = env.home + [op.rename(name, name)]
> res = sess.compound(ops)
> check(res, NFS4ERR_NOFILEHANDLE, "RENAME with no <sfh>")
> + sess.destroy()
>
> # FRED - can't test No Cfh, with a Sfh
>
> @@ -303,6 +323,7 @@ def testNonExistent(t, env):
> check(res)
> res = rename_obj(sess, basedir + ['foo'], basedir + ['bar'])
> check(res, NFS4ERR_NOENT, "RENAME on non-existing object %s/foo" % name)
> + sess.destroy()
>
> def testZeroLengthOldname(t, env):
> """RENAME with zero length oldname should return NFS4ERR_INVAL
> @@ -318,6 +339,7 @@ def testZeroLengthOldname(t, env):
> check(res)
> res = rename_obj(sess, basedir + [''], basedir + ['bar'])
> check(res, NFS4ERR_INVAL, "RENAME with zero length oldname")
> + sess.destroy()
>
> def testZeroLengthNewname(t, env):
> """RENAME with zero length newname should return NFS4ERR_INVAL
> @@ -333,6 +355,7 @@ def testZeroLengthNewname(t, env):
> check(res)
> res = rename_obj(sess, basedir + ['foo'], basedir + [''])
> check(res, NFS4ERR_INVAL, "RENAME with zero length newname")
> + sess.destroy()
>
> def testBadutf8Oldname(t, env):
> """RENAME with non-UTF8 oldname should return NFS4ERR_INVAL
> @@ -350,6 +373,7 @@ def testBadutf8Oldname(t, env):
> res = rename_obj(sess, basedir + [bad_utf8], basedir + [name])
> check(res, NFS4ERR_INVAL, "RENAME with non-UTF8 oldname %s/%s" %
> (name, repr(bad_utf8)[1:-1]))
> + sess.destroy()
>
> def testBadutf8Newname(t, env):
> """RENAME with non-UTF8 newname should return NFS4ERR_INVAL
> @@ -366,6 +390,7 @@ def testBadutf8Newname(t, env):
> res = rename_obj(sess, basedir + [name], basedir + [bad_utf8])
> check(res, NFS4ERR_INVAL, "RENAME with non-UTF8 newname %s/%s" %
> (name, repr(bad_utf8)[1:-1]))
> + sess.destroy()
>
> def testDotsOldname(t, env):
> """RENAME from nonexistant . or .. should return _NOENT/_BADNAME
> @@ -384,6 +409,7 @@ def testDotsOldname(t, env):
> res = rename_obj(sess, basedir + ['..'], basedir + [name])
> check(res, NFS4ERR_BADNAME, "RENAME from nonexistant '..'",
> [NFS4ERR_NOENT])
> + sess.destroy()
>
> def testDotsNewname(t, env):
> """RENAME into . or .. should return _BADNAME or NFS4_OK
> @@ -402,6 +428,7 @@ def testDotsNewname(t, env):
> res = rename_obj(sess, basedir + [name], basedir + ['..'])
> check(res, NFS4ERR_BADNAME, "RENAME into '..'",
> [NFS4_OK])
> + sess.destroy()
>
> def testDirToObj(t, env):
> """RENAME dir into existing nondir should return NFS4ERR_EXIST
> @@ -416,6 +443,7 @@ def testDirToObj(t, env):
> maketree(sess, [name, ['dir'], 'file'])
> res = rename_obj(sess, basedir + ['dir'], basedir + ['file'])
> check(res, NFS4ERR_EXIST, "RENAME dir into existing file")
> + sess.destroy()
>
> def testDirToDir(t, env):
> """RENAME dir into existing, empty dir should retrun NFS4_OK
> @@ -430,6 +458,7 @@ def testDirToDir(t, env):
> maketree(sess, [name, ['dir1', ['foo']], ['dir2']])
> res = rename_obj(sess, basedir + ['dir1'], basedir + ['dir2'])
> check(res, msg="RENAME dir1 into existing, empty dir2")
> + sess.destroy()
>
> def testFileToDir(t, env):
> """RENAME file into existing dir should return NFS4ERR_EXIST
> @@ -444,6 +473,7 @@ def testFileToDir(t, env):
> maketree(sess, [name, ['dir'], 'file'])
> res = rename_obj(sess, basedir + ['file'], basedir + ['dir'])
> check(res, NFS4ERR_EXIST, "RENAME file into existing dir")
> + sess.destroy()
>
> def testFileToFile(t, env):
> """RENAME file into existing file should return NFS4_OK
> @@ -458,6 +488,7 @@ def testFileToFile(t, env):
> maketree(sess, [name, 'file1', 'file2'])
> res = rename_obj(sess, basedir + ['file1'], basedir + ['file2'])
> check(res, msg="RENAME file1 into existing file2")
> + sess.destroy()
>
> def testDirToFullDir(t, env):
> """RENAME dir into existing, nonempty dir should return NFS4ERR_EXIST
> @@ -472,6 +503,7 @@ def testDirToFullDir(t, env):
> maketree(sess, [name, ['dir1'], ['dir2', ['foo']]])
> res = rename_obj(sess, basedir + ['dir1'], basedir + ['dir2'])
> check(res, NFS4ERR_EXIST, "RENAME dir1 into existing, nonempty dir2")
> + sess.destroy()
>
> def testFileToFullDir(t, env):
> """RENAME file into existing, nonempty dir should return NFS4ERR_EXIST
> @@ -486,6 +518,7 @@ def testFileToFullDir(t, env):
> maketree(sess, [name, 'file', ['dir', ['foo']]])
> res = rename_obj(sess, basedir + ['file'], basedir + ['dir'])
> check(res, NFS4ERR_EXIST, "RENAME file into existing, nonempty dir")
> + sess.destroy()
>
> def testSelfRenameDir(t, env):
> """RENAME that does nothing
> @@ -505,6 +538,7 @@ def testSelfRenameDir(t, env):
> if scinfo.before != scinfo.after or tcinfo.before != tcinfo.after:
> t.fail("RENAME of dir %s into itself should do nothing, "
> "but cinfo was changed" % name)
> + sess.destroy()
>
> def testSelfRenameFile(t, env):
> """RENAME that does nothing
> @@ -524,6 +558,7 @@ def testSelfRenameFile(t, env):
> if scinfo.before != scinfo.after or tcinfo.before != tcinfo.after:
> t.fail("RENAME of file %s into itself should do nothing, "
> "but cinfo was changed" % name)
> + sess.destroy()
>
> def testLinkRename(t, env):
> """RENAME of file into its hard link should do nothing
> @@ -545,3 +580,4 @@ def testLinkRename(t, env):
> if scinfo.before != scinfo.after or tcinfo.before != tcinfo.after:
> t.fail("RENAME of file into its hard link should do nothing, "
> "but cinfo was changed")
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_secinfo.py b/nfs4.1/server41tests/st_secinfo.py
> index c0e5b71..381898d 100644
> --- a/nfs4.1/server41tests/st_secinfo.py
> +++ b/nfs4.1/server41tests/st_secinfo.py
> @@ -29,6 +29,7 @@ def testSupported(t, env):
> # Just do a simple SECINFO
> res = sess.compound([op.putfh(fh), op.secinfo(name)])
> check(res)
> + sess.destroy()
>
> def testSupported2(t, env):
> """GETFH after do a SECINFO_NO_NAME or SECINFO
> @@ -55,3 +56,4 @@ def testSupported2(t, env):
> # GETFH after do a SECINFO should get error NFS4ERR_NOFILEHANDLE
> res = sess.compound([op.putfh(fh), op.secinfo(name), op.getfh()])
> check(res, NFS4ERR_NOFILEHANDLE)
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_secinfo_no_name.py b/nfs4.1/server41tests/st_secinfo_no_name.py
> index 14bc410..cc2c30f 100644
> --- a/nfs4.1/server41tests/st_secinfo_no_name.py
> +++ b/nfs4.1/server41tests/st_secinfo_no_name.py
> @@ -18,6 +18,7 @@ def testSupported(t, env):
> # Do a simple SECINFO_NO_NAME
> res = sess.compound([op.putrootfh(), op.secinfo_no_name(0)])
> check(res)
> + sess.destroy()
>
> def testSupported2(t, env):
> """GETFH after do a SECINFO_NO_NAME or SECINFO
> @@ -33,3 +34,4 @@ def testSupported2(t, env):
> res = sess.compound([op.putrootfh(), op.secinfo_no_name(0), op.getfh()])
> print res
> check(res, NFS4ERR_NOFILEHANDLE)
> + sess.destroy()
> diff --git a/nfs4.1/server41tests/st_sequence.py b/nfs4.1/server41tests/st_sequence.py
> index 7277290..9c2a756 100644
> --- a/nfs4.1/server41tests/st_sequence.py
> +++ b/nfs4.1/server41tests/st_sequence.py
> @@ -15,6 +15,7 @@ def testSupported(t, env):
> sess = c.create_session()
> res = sess.compound([])
> check(res)
> + sess.destroy()
>
> def testNotFirst(t, env):
> """SEQUENCE must be first
> @@ -26,6 +27,7 @@ def testNotFirst(t, env):
> sess = c.create_session()
> res = sess.compound([sess.seq_op()])
> check(res, NFS4ERR_SEQUENCE_POS)
> + sess.destroy()
>
> def testNotBound(t, env):
> """SEQUENCE sent on unbound connection
> @@ -70,6 +72,7 @@ def testImplicitBind(t, env):
> res = env.c1.compound([sess.seq_op()], pipe=rogue)
> check(res)
> env.c1.close(rogue)
> + sess.destroy()
>
> def testImplicitBind4a(t, env):
> """SEQUENCE sent on unbound connection will bind it if no enforcing done
> @@ -93,6 +96,7 @@ def testImplicitBind4a(t, env):
> print "B4"
> env.c1.close(rogue)
> print "B5"
> + sess.destroy()
>
> def xtestImplicitBind(t, env):
> """SEQUENCE sent on unbound connection will bind it if no enforcing done
> @@ -122,6 +126,7 @@ def xtestImplicitBind(t, env):
> res = c.compound([op.sequence(sid, seqid, 0, 0, True)], pipe=rogue)
> check(res)
> c.close(rogue)
> + sess.destroy()
>
> def testBadSession(t, env):
> """SEQUENCE sent on unknown session
> @@ -148,6 +153,7 @@ def testRequestTooBig(t, env):
> res = sess1.compound([op.putrootfh(), op.lookup("12345"*100)])
> # FIXME - NAME_TOO_BIG is valid, don't want it to be
> check(res, NFS4ERR_REQ_TOO_BIG)
> + sess1.destroy()
>
> def testTooManyOps(t, env):
> """Send a request with more ops than the session can handle
> @@ -168,6 +174,7 @@ def testTooManyOps(t, env):
> lots_of_ops += [op.getattr(0)]
> res = sess1.compound(lots_of_ops)
> check(res, NFS4ERR_TOO_MANY_OPS)
> + sess1.destroy()
>
> def testBadSlot(t, env):
> """Send a request with a bad slot
> @@ -182,6 +189,7 @@ def testBadSlot(t, env):
> # Send sequence on (non-existant) slot number 8
> res = env.c1.compound([op.sequence(sess1.sessionid, 1, 8, 8, True)])
> check(res, NFS4ERR_BADSLOT)
> + sess1.destroy()
>
> def testReplayCache001(t, env):
> """Send two successful idempotent compounds with same seqid
> @@ -198,6 +206,7 @@ def testReplayCache001(t, env):
> res1.tag = res2.tag = ""
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
> + sess1.destroy()
>
> def testReplayCache002(t, env):
> """Send two successful non-idempotent compounds with same seqid
> @@ -218,6 +227,7 @@ def testReplayCache002(t, env):
> res1.tag = res2.tag = ""
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
> + sess1.destroy()
>
> def testReplayCache003(t, env):
> """Send two unsuccessful idempotent compounds with same seqid
> @@ -234,6 +244,7 @@ def testReplayCache003(t, env):
> res1.tag = res2.tag = ""
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
> + sess1.destroy()
>
> def testReplayCache004(t, env):
> """Send two unsuccessful non-idempotent compounds with same seqid
> @@ -251,6 +262,7 @@ def testReplayCache004(t, env):
> res1.tag = res2.tag = ""
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
> + sess1.destroy()
>
> def testReplayCache005(t, env):
> """Send two unsupported compounds with same seqid
> @@ -267,6 +279,7 @@ def testReplayCache005(t, env):
> res1.tag = res2.tag = ""
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
> + sess1.destroy()
>
> def testReplayCache006(t, env):
> """Send two solo sequence compounds with same seqid
> @@ -283,6 +296,7 @@ def testReplayCache006(t, env):
> res1.tag = res2.tag = ""
> if not nfs4lib.test_equal(res1, res2):
> fail("Replay results not equal")
> + sess1.destroy()
>
> def testReplayCache007(t, env):
> """Send two successful non-idempotent compounds with same seqid and False cache_this
> @@ -300,6 +314,7 @@ def testReplayCache007(t, env):
> check(res1, NFS4_OK)
> res2 = sess1.compound(ops, seq_delta=0, cache_this=False)
> check(res2, NFS4ERR_RETRY_UNCACHED_REP)
> + sess1.destroy()
>
> def testOpNotInSession(t, env):
> """Operations other than SEQUENCE, BIND_CONN_TO_SESSION, EXCHANGE_ID,
> @@ -338,6 +353,7 @@ def testSessionidSequenceidSlotid(t, env):
>
> if not nfs4lib.test_equal(res.resarray[0].sr_slotid, 2, "int"):
> fail("server return bad slotid")
> + sess1.destroy()
>
> def testBadSequenceidAtSlot(t, env):
> """ If the difference between sa_sequenceid and the server's cached
> @@ -363,6 +379,7 @@ def testBadSequenceidAtSlot(t, env):
>
> res = c.c.compound([op.sequence(sid, nfs4lib.dec_u32(seqid), 2, 3, True)])
> check(res, NFS4ERR_SEQ_MISORDERED)
> + sess1.destroy()
>
> def testReuseSlotID(t, env):
> """ If client reuses a slot ID and sequence ID for a completely
> @@ -392,3 +409,4 @@ def testReuseSlotID(t, env):
> res = c.c.compound([op.sequence(sid, seqid, 0, 0, TRUE)] +
> nfs4lib.use_obj(dir) + [op.rename(name, "test")])
> check(res)
> + sess1.destroy()
> diff --git a/nfs4.1/server41tests/st_trunking.py b/nfs4.1/server41tests/st_trunking.py
> index d99f80f..a0b4281 100644
> --- a/nfs4.1/server41tests/st_trunking.py
> +++ b/nfs4.1/server41tests/st_trunking.py
> @@ -23,6 +23,8 @@ def testTwoSessions(t, env):
> c = env.c1.new_client(env.testname(t))
> sess = c.create_session()
> sess2 = c.create_session()
> + sess.destroy()
> + sess2.destroy()
>
>
> def testUseTwoSessions(t, env):
> @@ -42,6 +44,8 @@ def testUseTwoSessions(t, env):
> check(res)
> res = sess2.compound([])
> check(res)
> + sess.destroy()
> + sess2.destroy()
>
> # create client
> # create session
> diff --git a/nfs4.1/server41tests/st_verify.py b/nfs4.1/server41tests/st_verify.py
> index a1bc5ca..d6e62f1 100644
> --- a/nfs4.1/server41tests/st_verify.py
> +++ b/nfs4.1/server41tests/st_verify.py
> @@ -12,6 +12,7 @@ def _try_mand(t, env, path):
> ops = use_obj(path) + [op.verify(dict)] + use_obj(path)
> res = sess1.compound(ops)
> check(res, msg="Verifying mandatory attributes against getattr")
> + sess1.destroy()
>
> def _try_type(env, path, type):
> c = env.c1
> --
> 1.7.4.1
>
>
>

2011-04-20 09:31:42

by Mi Jinlong

[permalink] [raw]
Subject: Re: [PATCH 1/5] CLNT: try to destroy session after test complete



J. Bruce Fields:
> On Mon, Mar 28, 2011 at 04:57:59PM +0800, Mi Jinlong wrote:
>> When testing pynfs41, I got NFS4ERR_DELAY at some tests.
>> At a test case, we don't destroy the session after create.
>> So, this patch try to destroy session test complete.
>
> Sounds like a good idea.
>
> It seems a little tedious to have to do this by hand every time; could
> we do some automatic cleanup at the end of the test when the variable
> goes out of scope, or something like that?

I have try my best to find a automatic method to cleanup it,
but I can't get.

Maybe Fred can help us?


--
----
thanks
Mi Jinlong



2011-04-19 22:49:50

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH v2 3/5] CLNT: test reclaim after RECLAIM_COMPLETE

On Mon, Mar 28, 2011 at 04:59:37PM +0800, Mi Jinlong wrote:
> Signed-off-by: Mi Jinlong <[email protected]>

Looks fine but note you shouldn't need to go to the trouble of doing a
lock if you want to test reclaims--opens can also be reclaimed.

--b.

> ---
> nfs4.1/server41tests/st_reclaim_complete.py | 50 +++++++++++++++++++++++++++
> 1 files changed, 50 insertions(+), 0 deletions(-)
>
> diff --git a/nfs4.1/server41tests/st_reclaim_complete.py b/nfs4.1/server41tests/st_reclaim_complete.py
> index 5e3174c..4c9fc37 100644
> --- a/nfs4.1/server41tests/st_reclaim_complete.py
> +++ b/nfs4.1/server41tests/st_reclaim_complete.py
> @@ -1,9 +1,18 @@
> from st_create_session import create_session
> from nfs4_const import *
> from environment import check, fail, use_obj, create_file
> +from nfs4_type import open_owner4, locker4, open_to_lock_owner4
> import nfs4_ops as op
> import nfs4lib
>
> +def opt_result(res, opt=None):
> + """Get the corresponding result at res.resarray[]"""
> + if opt == None:
> + return
> + for resa in res.resarray:
> + if resa.resop == opt:
> + return resa
> +
> def testSupported(t, env):
> """Do a simple RECLAIM_COMPLETE
>
> @@ -20,3 +29,44 @@ def testSupported(t, env):
> res = sess.compound([op.reclaim_complete(FALSE)])
> check(res)
> sess.destroy()
> +
> +def testReclaimAfterRECC(t, env):
> + """If client does subsequent reclaims of locking state after
> + RECLAIM_COMPLETE is done, server will return NFS4ERR_NO_GRACE.
> + rfc5661 18.51.3
> +
> + FLAGS: reclaim_complete all
> + CODE: RECC2
> + """
> + name = env.testname(t)
> + c = env.c1.new_client(name)
> + sess = c.create_session()
> +
> + # RECLAIM_COMPLETE
> + res = sess.compound([op.reclaim_complete(FALSE)])
> + check(res)
> +
> + fname = "owner_%s" % name
> + path = sess.c.homedir + [name]
> + res = create_file(sess, fname, path, access=OPEN4_SHARE_ACCESS_BOTH)
> + check(res)
> +
> + # Get stateid from OPEN4resok for making a lockowner
> + nres = opt_result(res, OP_OPEN)
> + if nres == None:
> + fail("Can not get OPEN4resok!")
> + oseqid = nres.stateid
> +
> + owner = open_owner4(0, "My Open Owner")
> + otlowner = open_to_lock_owner4(0, oseqid, 0, owner)
> + lowner = locker4(TRUE, otlowner)
> +
> + # Get filehandle from GETFHresok for locking
> + nres = opt_result(res, OP_GETFH)
> + if nres == None:
> + fail("Can not get GETFHresok!")
> + cfh = nres.object
> +
> + res = sess.compound([op.putfh(cfh), op.lock(READ_LT, TRUE, 0, 1, lowner)])
> + check(res, NFS4ERR_NO_GRACE)
> + sess.destroy()
> --
> 1.7.4.1
>
>
>

2011-04-19 22:51:15

by J. Bruce Fields

[permalink] [raw]
Subject: Re: [PATCH 0/5] a pynfs41 problem and some tests about RECLAIM_COMPLETE

On a quick skim these look reasonable to me. Fred, are you catching up
with this stuff or should I continue queueing it up in my tree?

--b.

On Mon, Mar 28, 2011 at 04:50:51PM +0800, Mi Jinlong wrote:
> Fix a pynfs41 problem and some tests about RECLAIM_COMPLETE.
>
>
> --
> ----
> thanks
> Mi Jinlong
>