Port LockFileLock tests to C
Project: http://git-wip-us.apache.org/repos/asf/lucy/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy/commit/35388cd2 Tree: http://git-wip-us.apache.org/repos/asf/lucy/tree/35388cd2 Diff: http://git-wip-us.apache.org/repos/asf/lucy/diff/35388cd2 Branch: refs/heads/master Commit: 35388cd22600cb3c202cf11c8c9afd661c8f4fe4 Parents: e06cdbf Author: Nick Wellnhofer <[email protected]> Authored: Fri Feb 17 21:38:56 2017 +0100 Committer: Nick Wellnhofer <[email protected]> Committed: Mon Feb 20 16:48:17 2017 +0100 ---------------------------------------------------------------------- core/Lucy/Store/Lock.c | 18 -- core/Lucy/Store/Lock.cfh | 9 - go/lucy/store_test.go | 15 -- perl/t/105-folder.t | 36 +--- perl/t/106-locking.t | 89 ---------- perl/t/110-shared_lock.t | 93 ----------- perl/t/111-index_manager.t | 17 +- perl/t/core/106-lf_lock.t | 23 +++ test/Lucy/Test.c | 2 + test/Lucy/Test/Store/TestLock.c | 297 +++++++++++++++++++++++++++++++++ test/Lucy/Test/Store/TestLock.cfh | 29 ++++ 11 files changed, 356 insertions(+), 272 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/core/Lucy/Store/Lock.c ---------------------------------------------------------------------- diff --git a/core/Lucy/Store/Lock.c b/core/Lucy/Store/Lock.c index 90a6aa0..5cddcd9 100644 --- a/core/Lucy/Store/Lock.c +++ b/core/Lucy/Store/Lock.c @@ -77,16 +77,6 @@ Lock_Destroy_IMP(Lock *self) { SUPER_DESTROY(self, LOCK); } -String* -Lock_Get_Name_IMP(Lock *self) { - return Lock_IVARS(self)->name; -} - -String* -Lock_Get_Host_IMP(Lock *self) { - return Lock_IVARS(self)->host; -} - bool Lock_Obtain_Shared_IMP(Lock *self) { LockIVARS *const ivars = Lock_IVARS(self); @@ -163,14 +153,6 @@ LFLock_init(LockFileLock *self, Folder *folder, String *name, String *host, return self; } -String* -LFLock_Get_Lock_Path_IMP(LockFileLock *self) { - LockFileLockIVARS *const ivars = LFLock_IVARS(self); - return ivars->shared_lock_path - ? ivars->shared_lock_path - : ivars->lock_path; -} - struct lockfile_context { OutStream *outstream; String *json; http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/core/Lucy/Store/Lock.cfh ---------------------------------------------------------------------- diff --git a/core/Lucy/Store/Lock.cfh b/core/Lucy/Store/Lock.cfh index 6688e95..30940b4 100644 --- a/core/Lucy/Store/Lock.cfh +++ b/core/Lucy/Store/Lock.cfh @@ -96,12 +96,6 @@ abstract class Lucy::Store::Lock inherits Clownfish::Obj { public abstract void Release(Lock *self); - String* - Get_Name(Lock *self); - - String* - Get_Host(Lock *self); - public void Destroy(Lock *self); } @@ -131,9 +125,6 @@ class Lucy::Store::LockFileLock nickname LFLock public void Release(LockFileLock *self); - String* - Get_Lock_Path(LockFileLock *self); - public void Destroy(LockFileLock *self); } http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/go/lucy/store_test.go ---------------------------------------------------------------------- diff --git a/go/lucy/store_test.go b/go/lucy/store_test.go index ae70069..2b24ff4 100644 --- a/go/lucy/store_test.go +++ b/go/lucy/store_test.go @@ -652,21 +652,10 @@ func TestLockFileLockAll(t *testing.T) { lock := NewLockFileLock(folder, "foo", "dev.example.com", 0, 1, false) other := NewLockFileLock(folder, "foo", "dev.example.com", 0, 1, false) - if got := lock.getName(); got != "foo" { - t.Errorf("getName: %v", got) - } - if got := lock.getHost(); got != "dev.example.com" { - t.Errorf("getHost: %v", got) - } - err = lock.RequestShared() if err != nil { t.Errorf("Request: %v", err) } - if got := lock.getLockPath(); len(got) == 0 { - // Lock path only valid when locked for shared locks. - t.Errorf("getLockPath should work") - } err = other.RequestShared() if err != nil { t.Errorf("Shared lock Request should succeed: %v", err) @@ -686,10 +675,6 @@ func TestLockFileLockAll(t *testing.T) { if err != nil { t.Errorf("Request: %v", err) } - if got := lock.getLockPath(); len(got) == 0 { - // Lock path only valid when locked for shared locks. - t.Errorf("getLockPath should work") - } err = other.RequestExclusive() if err == nil { t.Errorf("Request should fail for locked resource") http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/perl/t/105-folder.t ---------------------------------------------------------------------- diff --git a/perl/t/105-folder.t b/perl/t/105-folder.t index ba1255e..002642f 100644 --- a/perl/t/105-folder.t +++ b/perl/t/105-folder.t @@ -17,7 +17,7 @@ use strict; use warnings; use lib 'buildlib'; -use Test::More tests => 25; +use Test::More tests => 17; use File::Spec::Functions qw( catfile ); use Fcntl; use Lucy::Test::TestUtils qw( init_test_index_loc ); @@ -46,43 +46,13 @@ for my $folder ( $fs_folder, $ram_folder ) { my $slurped = $folder->slurp_file('king_of_rock'); is( $slurped, $king, "slurp_file works" ); - my $lock = Lucy::Store::LockFileLock->new( - host => '', - folder => $folder, - name => 'lock_robster', - timeout => 0, - exclusive_only => 1, - ); - my $competing_lock = Lucy::Store::LockFileLock->new( - host => '', - folder => $folder, - name => 'lock_robster', - timeout => 0, - exclusive_only => 1, - ); - - $lock->obtain_exclusive(); - my $lock_path = $lock->get_lock_path; - ok( $folder->exists($lock_path), "lock is locked" ); - ok( !$competing_lock->obtain_exclusive(), - "shouldn't get lock on existing resource" - ); - ok( $folder->exists($lock_path), - "lock still locked after competing attempt" - ); - - $lock->release; - ok( !$folder->exists($lock_path), "release works" ); - - $lock->obtain_exclusive(); $folder->rename( from => 'king_of_rock', to => 'king_of_lock' ); - $lock->release; ok( !$folder->exists('king_of_rock'), - "file successfully removed while locked" + "file successfully removed" ); is( $folder->exists('king_of_lock'), - 1, "file successfully moved while locked" ); + 1, "file successfully moved" ); is( $folder->open_out("king_of_lock"), undef, "open_out returns undef when file exists" ); http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/perl/t/106-locking.t ---------------------------------------------------------------------- diff --git a/perl/t/106-locking.t b/perl/t/106-locking.t deleted file mode 100644 index 15c6a3a..0000000 --- a/perl/t/106-locking.t +++ /dev/null @@ -1,89 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -use strict; -use warnings; -use lib 'buildlib'; - -use Time::HiRes qw( sleep ); -use Test::More; -use File::Spec::Functions qw( catfile ); -use Lucy::Test::TestUtils qw( init_test_index_loc ); - -BEGIN { - if ( $^O =~ /(mswin|cygwin)/i ) { - plan( 'skip_all', "fork on Windows not supported by Lucy" ); - } - else { - plan( tests => 3 ); - } -} - -my $path = init_test_index_loc(); - -Dead_locks_are_removed: { - my $lock_path = catfile( $path, 'locks', 'foo.lock' ); - - # Remove any existing lockfile - unlink $lock_path; - die "Can't unlink '$lock_path'" if -e $lock_path; - - my $folder = Lucy::Store::FSFolder->new( path => $path ); - - sub make_lock { - my $lock = Lucy::Store::LockFileLock->new( - timeout => 0, - name => 'foo', - host => '', - exclusive_only => 1, - @_ - ); - $lock->obtain_exclusive() or die "no dice"; - return $lock; - } - - # Fork a process that will create a lock and then exit - my $pid = fork(); - if ( $pid == 0 ) { # child - make_lock( folder => $folder ); - exit; - } - else { - waitpid( $pid, 0 ); - } - - sleep .1; - ok( -e $lock_path, "child secured lock" ); - - # The locking attempt will fail if the pid from the process that made the - # lock is active, so do the best we can to see whether another process - # started up with the child's pid (which would be weird). - my $pid_active = kill( 0, $pid ); - - eval { make_lock( folder => $folder, host => 'somebody_else' ) }; - like( $@, qr/no dice/, "different host fails to get lock" ); - - eval { make_lock( folder => $folder ) }; - warn $@ if $@; - my $saved_err = $@; - $pid_active ||= kill( 0, $pid ); -SKIP: { - skip( "Child's pid is active", 1 ) if $pid_active; - ok( !$saved_err, - 'second lock attempt clobbered dead lock file and did not die' ); - } - - undef $folder; -} http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/perl/t/110-shared_lock.t ---------------------------------------------------------------------- diff --git a/perl/t/110-shared_lock.t b/perl/t/110-shared_lock.t deleted file mode 100644 index 86e7d6c..0000000 --- a/perl/t/110-shared_lock.t +++ /dev/null @@ -1,93 +0,0 @@ -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -use strict; -use warnings; - -use Test::More tests => 14; -use Lucy::Test; - -my $folder = Lucy::Store::RAMFolder->new; -my @args = ( - folder => $folder, - name => 'ness', - timeout => 0, - host => 'nessie', - exclusive_only => 0, -); - -my $ex_lock = Lucy::Store::LockFileLock->new(@args); - -sub is_locked { - if ($ex_lock->request_exclusive) { - $ex_lock->release; - return 0; - } - else { - return 1; - } -} - -my $lock = Lucy::Store::LockFileLock->new(@args); - -ok( !is_locked(), "not locked yet" ); - -ok( $lock->obtain_shared(), "obtain" ); -ok( is_locked(), "is_locked" ); -ok( $folder->exists('locks/ness-1.lock'), "lockfile exists" ); - -my $another_lock = Lucy::Store::LockFileLock->new(@args); -ok( $another_lock->obtain_shared(), "got a second lock on the same resource" ); - -$lock->release; -ok( is_locked(), - "first lock released but still is_locked because of other lock" ); - -my $ya_lock = Lucy::Store::LockFileLock->new(@args); -ok( $ya_lock->obtain_shared(), "got yet another lock" ); - -ok( $lock->obtain_shared(), "got first lock again" ); -is( $lock->get_lock_path, "locks/ness-3.lock", - "first lock uses a different lock_path now" ); - -# Rewrite lock file to spec a different pid. -my $content = $folder->slurp_file("locks/ness-3.lock"); -$content =~ s/$$/123456789/; -$folder->delete('locks/ness-3.lock') or die "Can't delete 'ness-3.lock'"; -my $outstream = $folder->open_out('locks/ness-3.lock') - or die Clownfish->error; -$outstream->print($content); -$outstream->close; - -$lock->release; -$another_lock->release; -$ya_lock->release; - -ok( $lock->get_lock_path, "failed to release a lock with a different pid" ); -ok( !is_locked(), "is_locked clears stale locks" ); - -ok( $lock->obtain_shared(), "got lock again" ); -ok( is_locked(), "it's locked" ); - -# Rewrite lock file to spec a different host. -$content = $folder->slurp_file("locks/ness-1.lock"); -$content =~ s/nessie/sting/; -$folder->delete('locks/ness-1.lock') or die "Can't delete 'ness-1.lock'"; -$outstream = $folder->open_out('locks/ness-1.lock') or die Clownfish->error; -$outstream->print($content); -$outstream->close; - -$lock->release; -ok( is_locked(), "don't delete lock belonging to another host" ); http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/perl/t/111-index_manager.t ---------------------------------------------------------------------- diff --git a/perl/t/111-index_manager.t b/perl/t/111-index_manager.t index d42ae98..dd7d8d0 100644 --- a/perl/t/111-index_manager.t +++ b/perl/t/111-index_manager.t @@ -32,24 +32,11 @@ sub recycle { package main; -use Test::More tests => 11; +use Test::More tests => 8; use Lucy::Test; -my $folder = Lucy::Store::RAMFolder->new; - -my $lock = Lucy::Store::LockFileLock->new( - folder => $folder, - host => 'me', - name => 'angie', - timeout => 1000, - exclusive_only => 0, -); -isa_ok( $lock, 'Lucy::Store::Lock', "make_lock" ); -is( $lock->get_name, "angie", "correct lock name" ); -is( $lock->get_host, "me", "correct host" ); - my $schema = Lucy::Test::TestSchema->new; -$folder = Lucy::Store::RAMFolder->new; +my $folder = Lucy::Store::RAMFolder->new; for ( 1 .. 20 ) { my $indexer = Lucy::Index::Indexer->new( http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/perl/t/core/106-lf_lock.t ---------------------------------------------------------------------- diff --git a/perl/t/core/106-lf_lock.t b/perl/t/core/106-lf_lock.t new file mode 100644 index 0000000..db99bc4 --- /dev/null +++ b/perl/t/core/106-lf_lock.t @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +use strict; +use warnings; + +use Lucy::Test; +my $success = Lucy::Test::run_tests("Lucy::Test::Store::TestLockFileLock"); + +exit($success ? 0 : 1); + http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/test/Lucy/Test.c ---------------------------------------------------------------------- diff --git a/test/Lucy/Test.c b/test/Lucy/Test.c index 22223e1..2a30a68 100644 --- a/test/Lucy/Test.c +++ b/test/Lucy/Test.c @@ -75,6 +75,7 @@ #include "Lucy/Test/Store/TestIOChunks.h" #include "Lucy/Test/Store/TestIOPrimitives.h" #include "Lucy/Test/Store/TestInStream.h" +#include "Lucy/Test/Store/TestLock.h" #include "Lucy/Test/Store/TestRAMDirHandle.h" #include "Lucy/Test/Store/TestRAMFileHandle.h" #include "Lucy/Test/Store/TestRAMFolder.h" @@ -114,6 +115,7 @@ Test_create_test_suite() { TestSuite_Add_Batch(suite, (TestBatch*)TestFSFolder_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestRAMFolder_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestFolder_new()); + TestSuite_Add_Batch(suite, (TestBatch*)TestLFLock_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestIxManager_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestCFWriter_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestCFReader_new()); http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/test/Lucy/Test/Store/TestLock.c ---------------------------------------------------------------------- diff --git a/test/Lucy/Test/Store/TestLock.c b/test/Lucy/Test/Store/TestLock.c new file mode 100644 index 0000000..f606e7b --- /dev/null +++ b/test/Lucy/Test/Store/TestLock.c @@ -0,0 +1,297 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TESTLUCY_USE_SHORT_NAMES +#include "Lucy/Util/ToolSet.h" + +#include "charmony.h" + +// rmdir +#ifdef CHY_HAS_DIRECT_H + #include <direct.h> +#endif +#ifdef CHY_HAS_UNISTD_H + #include <unistd.h> +#endif + +#include "Lucy/Test/Store/TestLock.h" +#include "Clownfish/TestHarness/TestBatchRunner.h" +#include "Lucy/Store/FSFolder.h" +#include "Lucy/Store/Lock.h" +#include "Lucy/Store/RAMFolder.h" +#include "Lucy/Util/Json.h" + +TestLockFileLock* +TestLFLock_new() { + return (TestLockFileLock*)Class_Make_Obj(TESTLOCKFILELOCK); +} + +static Folder* +S_create_fs_folder() { + Folder *folder = (Folder*)FSFolder_new(SSTR_WRAP_C("_locktest")); + Folder_Initialize(folder); + return folder; +} + +static void +S_destroy_fs_folder(Folder *folder) { + Folder_Delete_Tree(folder, SSTR_WRAP_C("locks")); + rmdir("_locktest"); + DECREF(folder); +} + +static void +test_exclusive_only(TestBatchRunner *runner, Lock *lock1, Lock *lock2, + const char *tag) { + TEST_TRUE(runner, Lock_Request_Exclusive(lock1), + "Request_Exclusive (only) succeeds %s", tag); + Err_set_error(NULL); + TEST_FALSE(runner, Lock_Request_Exclusive(lock2), + "Request_Exclusive (only) after Request_Exclusive fails %s", + tag); + TEST_TRUE(runner, CERTIFY(Err_get_error(), LOCKERR), + "Request_Exclusive (only) after Request_Exclusive sets" + " LockErr %s", tag); + Lock_Release(lock1); + + TEST_TRUE(runner, Lock_Request_Exclusive(lock2), + "Request_Exclusive (only) succeeds after Release %s", tag); + TEST_FALSE(runner, Lock_Request_Exclusive(lock1), + "Request_Exclusive (only) fails if lock2 is locked %s", tag); + Lock_Release(lock2); + + DECREF(lock2); + DECREF(lock1); +} + +static void +test_lock(TestBatchRunner *runner, Lock *lock1, Lock *lock2, Lock *lock3, + const char *tag) { + TEST_TRUE(runner, Lock_Request_Shared(lock1), "Request_Shared succeeds %s", + tag); + TEST_TRUE(runner, Lock_Request_Shared(lock2), + "Request_Shared on another lock succeeds %s", tag); + Err_set_error(NULL); + TEST_FALSE(runner, Lock_Request_Exclusive(lock3), + "Request_Exclusive after Request_Shared fails %s", tag); + TEST_TRUE(runner, CERTIFY(Err_get_error(), LOCKERR), + "Request_Exclusive after Request_Shared sets LockErr %s", tag); + Lock_Release(lock1); + Lock_Release(lock2); + + TEST_TRUE(runner, Lock_Request_Exclusive(lock1), + "Request_Exclusive succeeds %s", tag); + Err_set_error(NULL); + TEST_FALSE(runner, Lock_Request_Shared(lock2), + "Request_Shared after Request_Exclusive fails %s", tag); + TEST_TRUE(runner, CERTIFY(Err_get_error(), LOCKERR), + "Request_Shared after Request_Exclusive sets LockErr %s", tag); + Err_set_error(NULL); + TEST_FALSE(runner, Lock_Request_Exclusive(lock3), + "Request_Exclusive after Request_Exclusive fails %s", tag); + TEST_TRUE(runner, CERTIFY(Err_get_error(), LOCKERR), + "Request_Exclusive after Request_Exclusive sets LockErr %s", + tag); + Lock_Release(lock1); + + TEST_TRUE(runner, Lock_Request_Exclusive(lock3), + "Request_Exclusive succeeds after Release %s", tag); + Lock_Release(lock3); + + DECREF(lock3); + DECREF(lock2); + DECREF(lock1); +} + +static void +test_change_pid(TestBatchRunner *runner, Folder *folder, String *path, + const char *tag) { + Hash *hash = (Hash*)Json_slurp_json(folder, path); + TEST_TRUE(runner, CERTIFY(hash, HASH), "Lock file %s exists %s", + Str_Get_Ptr8(path), tag); + Hash_Store(hash, SSTR_WRAP_C("pid"), (Obj*)Str_newf("10000000")); + Folder_Delete(folder, path); + Json_spew_json((Obj*)hash, folder, path); + DECREF(hash); +} + +static void +test_stale(TestBatchRunner *runner, Folder *folder, const char *tag) { + String *name = SSTR_WRAP_C("test"); + String *host1 = SSTR_WRAP_C("fuchur"); + String *host2 = SSTR_WRAP_C("drogon"); + LockFileLock *lock1 = LFLock_new(folder, name, host1, 0, 100, false); + LockFileLock *lock2 = LFLock_new(folder, name, host2, 0, 100, false); + LockFileLock *tmp; + + tmp = LFLock_new(folder, name, host1, 0, 100, false); + LFLock_Request_Exclusive(tmp); + DECREF(tmp); + test_change_pid(runner, folder, SSTR_WRAP_C("locks/test.lock"), tag); + TEST_FALSE(runner, LFLock_Request_Exclusive(lock2), + "Lock_Exclusive fails with other host's exclusive lock %s", + tag); + TEST_TRUE(runner, LFLock_Request_Exclusive(lock1), + "Lock_Exclusive succeeds with stale exclusive lock %s", tag); + LFLock_Release(lock1); + + tmp = LFLock_new(folder, name, host1, 0, 100, false); + LFLock_Request_Shared(tmp); + DECREF(tmp); + test_change_pid(runner, folder, SSTR_WRAP_C("locks/test-1.lock"), tag); + TEST_FALSE(runner, LFLock_Request_Exclusive(lock2), + "Lock_Exclusive fails with other host's shared lock %s", tag); + TEST_TRUE(runner, LFLock_Request_Exclusive(lock1), + "Lock_Exclusive succeeds with stale shared files %s", tag); + LFLock_Release(lock1); + + DECREF(lock2); + DECREF(lock1); +} + +static void +test_Obtain(TestBatchRunner *runner, Lock *lock1, Lock *lock2, + const char *tag) { + TEST_TRUE(runner, Lock_Obtain_Shared(lock1), "Obtain_Shared succeeds %s", + tag); + TEST_FALSE(runner, Lock_Obtain_Exclusive(lock2), + "Obtain_Exclusive after Obtain_Shared fails %s", tag); + Lock_Release(lock1); + + TEST_TRUE(runner, Lock_Obtain_Exclusive(lock1), + "Obtain_Exclusive succeeds %s", tag); + TEST_FALSE(runner, Lock_Obtain_Shared(lock2), + "Obtain_Shared after Obtain_Exclusive fails %s", tag); + Lock_Release(lock1); + + DECREF(lock2); + DECREF(lock1); +} + +static void +S_try_request_shared(void *context) { + Lock_Request_Shared((Lock*)context); +} + +static void +S_try_request_exclusive(void *context) { + Lock_Request_Exclusive((Lock*)context); +} + +static void +S_try_release(void *context) { + Lock_Release((Lock*)context); +} + +static void +test_double_request_release(TestBatchRunner *runner, Lock *lock, + const char *tag) { + Err *err; + + Lock_Request_Shared(lock); + err = Err_trap(S_try_request_shared, lock); + TEST_TRUE(runner, err, "Request_Shared/Request_Shared fails %s", + tag); + DECREF(err); + Lock_Release(lock); + + Lock_Request_Exclusive(lock); + err = Err_trap(S_try_request_shared, lock); + TEST_TRUE(runner, err, "Request_Shared/Request_Exclusive fails %s", + tag); + DECREF(err); + Lock_Release(lock); + + Lock_Request_Shared(lock); + err = Err_trap(S_try_request_exclusive, lock); + TEST_TRUE(runner, err, "Request_Exclusive/Request_Shared fails %s", + tag); + DECREF(err); + Lock_Release(lock); + + Lock_Request_Exclusive(lock); + err = Err_trap(S_try_request_exclusive, lock); + TEST_TRUE(runner, err, + "Request_Exclusive/Request_Exclusive fails %s", tag); + DECREF(err); + Lock_Release(lock); + + err = Err_trap(S_try_release, lock); + TEST_TRUE(runner, err, "Double Release fails"); + DECREF(err); + + DECREF(lock); +} + +static void +test_empty_lock_folder(TestBatchRunner *runner, Folder *folder, + const char *name, const char *tag) { + Vector *files = Folder_List_R(folder, SSTR_WRAP_C("locks")); + TEST_TRUE(runner, files, "Lock folder exists after %s tests %s", name, + tag); + TEST_UINT_EQ(runner, Vec_Get_Size(files), 0, + "Lock folder is empty after %s tests %s", name, tag); + DECREF(files); +} + +static void +test_lf_lock_with_folder(TestBatchRunner *runner, Folder *folder, + const char *tag) { + String *name = SSTR_WRAP_C("test"); + String *host = SSTR_WRAP_C("fuchur"); + LockFileLock *lock1, *lock2, *lock3; + + lock1 = LFLock_new(folder, name, host, 0, 100, true); + lock2 = LFLock_new(folder, name, host, 0, 100, true); + test_exclusive_only(runner, (Lock*)lock1, (Lock*)lock2, tag); + test_empty_lock_folder(runner, folder, "exclusive only", tag); + + lock1 = LFLock_new(folder, name, host, 0, 100, false); + lock2 = LFLock_new(folder, name, host, 0, 100, false); + lock3 = LFLock_new(folder, name, host, 0, 100, false); + test_lock(runner, (Lock*)lock1, (Lock*)lock2, (Lock*)lock3, tag); + test_empty_lock_folder(runner, folder, "lock", tag); + + lock1 = LFLock_new(folder, name, host, 10, 1, false); + lock2 = LFLock_new(folder, name, host, 10, 1, false); + test_Obtain(runner, (Lock*)lock1, (Lock*)lock2, tag); + test_empty_lock_folder(runner, folder, "Obtain", tag); + + lock1 = LFLock_new(folder, name, host, 0, 100, false); + test_double_request_release(runner, (Lock*)lock1, tag); + test_empty_lock_folder(runner, folder, "double", tag); + + test_stale(runner, folder, tag); + test_empty_lock_folder(runner, folder, "stale", tag); +} + +static void +test_lf_lock(TestBatchRunner *runner) { + Folder *fs_folder = S_create_fs_folder(); + test_lf_lock_with_folder(runner, fs_folder, "(FSFolder)"); + S_destroy_fs_folder(fs_folder); + + Folder *ram_folder = (Folder*)RAMFolder_new(NULL); + test_lf_lock_with_folder(runner, ram_folder, "(RAMFolder)"); + DECREF(ram_folder); +} + +void +TestLFLock_Run_IMP(TestLockFileLock *self, TestBatchRunner *runner) { + TestBatchRunner_Plan(runner, (TestBatch*)self, 80); + test_lf_lock(runner); +} + http://git-wip-us.apache.org/repos/asf/lucy/blob/35388cd2/test/Lucy/Test/Store/TestLock.cfh ---------------------------------------------------------------------- diff --git a/test/Lucy/Test/Store/TestLock.cfh b/test/Lucy/Test/Store/TestLock.cfh new file mode 100644 index 0000000..b87cb7d --- /dev/null +++ b/test/Lucy/Test/Store/TestLock.cfh @@ -0,0 +1,29 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +parcel TestLucy; + +class Lucy::Test::Store::TestLockFileLock nickname TestLFLock + inherits Clownfish::TestHarness::TestBatch { + + inert incremented TestLockFileLock* + new(); + + void + Run(TestLockFileLock *self, TestBatchRunner *runner); +} + +
