おおむらです
ファイルロックユーティリティについていろいろ議論されているのですが、
ちゃんとフォローできてないおおむらです(なさけない)
で、みていると、ユーティリティの使い方についていろいろ議論されていて、
なかなかその真意が伝わっていない(みたい)なんですが、
それこそテストコードを先に書いて示せばよいのではないかと思います。
そこで、でしゃばりですみませんが、複数プロセスがあるときのテストの
フレームワークとして、こんなものを作ってみました。
これを使って、問題になっている点が明確に書けるとよいのですが
どうでしょう。
サンプルとして最近MLにあがっていた次の条件のテストケースを作って、
末尾にいれておきました。(LockFile_Test.java) 細部はいいかげんです。
1. プロセスAがロックを取得
2. プロセスAがロックを開放(deleteOnExit付き)
3. プロセスBがロックを取得
4. プロセスAが終了することで、プロセスBのロックファイルを削除
5. プロセスBがロック中にも関わらず、プロセスCがロックを取得し
ようとすると成功してしまう
------ TestAgentDriver_Test.java これがテストのパターンになります
import java.io.*;
import junit.framework.*;
public class TestAgentDriver_Test extends TestCase {
public TestAgentDriver_Test( String name ) { super( name ); }
public static Test suite() {
return new TestSuite( TestAgentDriver_Test.class );
}
public static void main(String args[]) {
junit.textui.TestRunner.run( suite() );
}
public void testGo() throws Exception {
TestAgentDriver tad = new TestAgentDriver( "java DummyTestAgent" );
tad.begin();
// usually, I test something here while running another process
// in this case the process is "java DummyTestAgent" and
// I check only the return value of the DummyTestAgent i.e. 1
int r = tad.end();
assertEquals( "proof of run", 1, r );
}
}
------ TestAgentDriver.java 別プロセスをコントロールするためのドライバ
import java.io.*;
public class TestAgentDriver {
private Process ps;
private PrintWriter pw;
public TestAgentDriver( String command ) {
try {
Runtime rt = Runtime.getRuntime();
ps = rt.exec( command );
pw = new PrintWriter( ps.getOutputStream() );
}
catch ( IOException ex ) {
ex.printStackTrace();
}
}
public void begin() {
pw.println( TestAgent.START );
}
public int end() {
pw.println( TestAgent.END );
pw.close();
try {
return ps.waitFor();
}
catch ( InterruptedException ex ){
ex.printStackTrace();
}
return 0;
}
}
------ TestAgent.java TestAgentDriverとのやりとりをする部分です。
import java.io.*;
public abstract class TestAgent {
abstract public void atBegin();
abstract public void proc();
abstract public int atEnd();
final public static String START = "start";
final public static String END = "end";
public int run() {
BufferedReader r = new BufferedReader( new InputStreamReader( System.in ) );
int v = 0;
try {
atBegin();
while( ! r.readLine().startsWith( START) ){};
proc();
while( ! r.readLine().startsWith( END ) ){};
v = atEnd();
}
catch ( IOException ex ){
ex.printStackTrace();
}
return v;
}
}
------ DummyTestAgent.java テスト用のヘルパープロセスに相当するものです。ここではほぼ空。
public class DummyTestAgent extends TestAgent {
public static void main( String[] args ) {
DummyTestAgent dta = new DummyTestAgent();
System.exit( dta.run() );
}
private int v;
public void atBegin() {
v = 0;
}
public void proc() {
v = 1;
}
public int atEnd() {
return v;
}
}
---- LockFile_Test.java
package XP.jp.co.esm.wiki.extremedomo.util;
import java.io.*;
import junit.framework.*;
public class LockFile_Test extends TestCase {
public LockFile_Test( String name ) { super( name ); }
public static Test suite() {
return new TestSuite( LockFile_Test.class );
}
public static void main(String args[]) {
junit.textui.TestRunner.run( suite() );
}
public void testLockOnTheFly() throws Exception {
TestAgentDriver pa = new TestAgentDriver( "java FileLockTestAgent" );
pa.begin();
/* FileLockTestAgentはこういうことをするとします
1. プロセスAがロックを取得
2. プロセスAがロックを開放(deleteOnExit付き)
*/
//3. プロセスBがロックを取得
TestAgentDriver pb = new TestAgentDriver( "java FileLockTestAgent" );
//4. プロセスAが終了することで、プロセスBのロックファイルを削除
pa.end();
//5. プロセスBがロック中にも関わらず、プロセスCがロックを取得し
// ようとすると成功してしまう
File lock = new File(".lck");
assertNull( "ロックできてはいけない", r );
pb.end();
}
}