[Ngms-svn] SVN-Commit: [66] [NMTree] add localCommit with unit test.

アーカイブの一覧に戻る

svnno****@sourc***** svnno****@sourc*****
2009年 12月 17日 (木) 12:48:47 JST


Revision: 66
          http://sourceforge.jp/projects/ngms/svn/view?view=rev&revision=66
Author:   osiire
Date:     2009-12-17 12:48:47 +0900 (Thu, 17 Dec 2009)

Log Message:
-----------
[NMTree] add localCommit with unit test.

Modified Paths:
--------------
    trunk/source/NMTree/src/info/ngms/nmtree/AbstractDescriptionElement.scala
    trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala
    trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala
    trunk/source/NMTree/src/info/ngms/nmtree/NMTree.scala
    trunk/source/NMTree/test/NMFileSystemTreeTest.scala
    trunk/source/NMTree/test/NMTreeBehavior.scala
    trunk/source/NMTree/test/NMTreeWithFileSystemTest.scala

Modified: trunk/source/NMTree/src/info/ngms/nmtree/AbstractDescriptionElement.scala
===================================================================
--- trunk/source/NMTree/src/info/ngms/nmtree/AbstractDescriptionElement.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/src/info/ngms/nmtree/AbstractDescriptionElement.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -6,15 +6,37 @@
 
 import scala.collection.mutable.LinkedHashMap
 
+/**
+ *  NMDescriptionのデータとするハッシュを保持するheaderと任意の文字列のリストを保持するbodyを持つ構造。
+ *  @version $Id$
+ *  @auther ogasa****@itpl*****
+ */
 trait AbstractDescriptionElement {
 
+    /**
+     * タグ(String)をキーとしてNMDescriptionsを保持する構造。
+     */
     val header : LinkedHashMap[String, NMDescription]
+
+    /**
+     * ヘッダ以下の任意のデータ行
+     */
     val body : List[String]
 
+    /**
+     * NMDescriptionのヘッダーをリスト型として返す関数。
+     * @return ヘッダとして登録されているNMDescriptionのリスト。順番が保持されている。
+     */
     def descriptions : List[NMDescription] = {
         header.values.toList
     }
 
+    /**
+     * 指定されたタグ文字列をキーとするNMDescriptionを検索する関数。
+     * @param tag 発見したいNMDescriptionに対応するタグ
+     * @return もし指定されたタグに対応するNMDescriptionが存在すれば、そのインスタンスをSomeコンストラクタで包んだ値が返される。
+     * 存在しなければNoneが返される。
+     */
     def find(tag : String) : Option[NMDescription] = {
         val nmlz_tag = DescriptionElement.normalizeTag(tag)
         try {
@@ -25,6 +47,12 @@
         }
     }
 
+    /**
+     * 指定されたタグ文字列をキーとするNMDescriptionを検索する関数。
+     * @param tag 発見したいNMDescriptionに対応するタグ
+     * @return もし指定されたタグに対応するNMDescriptionが存在すれば、そのインスタンスのvalueをSomeコンストラクタで包んだ値が返される。
+     * 存在しなければNoneが返される。
+     */
     def findVal(tag : String) : Option[String] = {
         val nmlz_tag = DescriptionElement.normalizeTag(tag)
         try {
@@ -35,6 +63,14 @@
         }
     }
 
+   /**
+    * 指定されたタグ文字列をキーとするNMDescriptionを使って指定された関数fを呼び出す関数。
+    * @param tag 発見したいNMDescriptionに対応するタグ
+    * @param default 指定したタグが存在しなかった場合、戻り値となる値
+    * @param f 指定したタグが存在した場合、そのタグに対応するNMDescriptionを引数として呼び出される関数。タグが存在しない場合は呼び出されない。
+    * @return もし指定されたタグに対応するNMDescriptionが存在すれば、関数fにNMDescriptionを適用した結果が返される。
+    * タグが存在しない場合は、defaultの値が返される。
+    */
     def findWith[A](tag : String) (default : A) (f : NMDescription => A) : A = {
         find(tag) match {
         case Some(desc) =>

Modified: trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala
===================================================================
--- trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/src/info/ngms/nmtree/NMFileSystemTree.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -30,28 +30,43 @@
 
     def createStream( path : NMPath ) : NMTree.TStreamElement = {
         val file = new File( path )
+        file.createNewFile()
         new {
             val input : InputStream = new FileInputStream( file )
             val output : OutputStream = new FileOutputStream( file )
+            def close : Unit =
+                input.close
+                output.close
         }
     }
 
+    def createDir( path : NMPath ) : Unit = {
+        val file = new File( path )
+        if( !file.mkdir() ) {
+            throw new LowLevelException("cannot create direcoty " + path )
+        }
+    }
+
     def createDescription( path : NMPath ) : NMTree.TDescriptionElement = {
+        val file = new File( path )
+        file.createNewFile()
         val h = new LinkedHashMap[String, NMDescription]()
         val b = Nil
         new AbstractDescriptionElement {
             val header = h
             val body = b
+            def close : Unit = ()
         }
     }
 
     def createTable( path : NMPath ) : NMTree.TTableElement = {
       // 未実装
       new {
-        val lines : Array[Array[String]] = Array(Array())
-        def foldl[T] (init : T) (f : (T, Array[String]) => T) : T = {
-          init
-        }
+          val lines : Array[Array[String]] = Array(Array())
+          def foldl[T] (init : T) (f : (T, Array[String]) => T) : T = {
+                  init
+          }
+          def close : Unit = ()
       }
     }
 
@@ -152,7 +167,9 @@
             if(recursive)
                 deleteFileRec( new File( path ) )
             else
-                ( new File( path ) ).delete
+                if( !( new File( path ) ).delete ) {
+                    throw new LowLevelException("cannot delete file " + path)
+                }
         }
 
         def symLink( src : NMPath, dst : NMPath ) : Unit = { }

Modified: trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala
===================================================================
--- trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/src/info/ngms/nmtree/NMPath.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -172,7 +172,7 @@
     }
 
     def concat ( path : String, child : String ) : String = {
-        path + separator + child
+        canonical(path) + separator + child
     }
 
     def diff( path : String, base : String) : String = {
@@ -236,6 +236,14 @@
     }
 
     /**
+     * 自身のパスがディレクトリかどうか判定する。
+     * @return 自身のパスがディレクトリであればtrue, そうでなければfalseが返される。
+     */
+    def isDir : Boolean = {
+        impl.pathOp.isNode( this )
+    }
+
+    /**
      * 自身のパスが持つ直下の子供のパスのリストを作成する。
      * @return 自身のパスが持つ直下の子供のパスのリストが返される。
      * 自身のパスに子供がいない場合は空リストが返される。

Modified: trunk/source/NMTree/src/info/ngms/nmtree/NMTree.scala
===================================================================
--- trunk/source/NMTree/src/info/ngms/nmtree/NMTree.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/src/info/ngms/nmtree/NMTree.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -101,17 +101,6 @@
          def delete( path : NMPath, recursive : Boolean ) : Unit
 
          /*
-          * シンボリックリンクを定義する関数。
-          * @param src リンクされる側のパス。
-          * @param dst リンクした結果新しく作成されるパス。
-          * @throws AppPermissionException
-          * @throws DestinationNotFoundException
-          * @throws DestinationAlreadyExistsException
-          * @throws LowLevelException
-          */
-         def symLink( src : NMPath, dst : NMPath ) : Unit
-
-         /*
           * エレメントのアクセス許可を定義する関数。
           * @param src アクセス許可を変更したいパス。
           * @param dst リンクした結果新しく作成されるパス。
@@ -173,6 +162,11 @@
          * ストリームへの書き込みを行うためのハンドラインスタンス。
          */
         val output : OutputStream
+
+        /*
+         * エレメントのクローズ処理
+         */
+        def close : Unit
     }
 
     /**
@@ -220,6 +214,11 @@
          * @param f 更新をするための関数。引数には現在のDescription情報が渡され、戻り値のDescription情報がエレメントへ反映される。
          */
         def update( f : List[NMDescription] => List[NMDescription] ) : Unit
+
+        /*
+         * エレメントのクローズ処理
+         */
+        def close : Unit
     }
 
     /**
@@ -239,6 +238,11 @@
          * @return 畳み込まれた値。
          */
         def foldl[T] (init : T) (f : (T, Array[String]) => T) : T
+
+        /*
+         * エレメントのクローズ処理
+         */
+        def close : Unit
     }
 
     /**
@@ -246,6 +250,7 @@
      */
     type NMTreeImplimentation = {
         def createStream( path : NMPath ) : TStreamElement
+        def createDir( path : NMPath ) : Unit
         def createDescription( path : NMPath ) : TDescriptionElement
         def createTable( path : NMPath ) : TTableElement
         def pathOp : TPathOperations
@@ -294,9 +299,17 @@
             true
         }
         def find( path : String ) : Option[NMTreeImplimentation] = {
-            // 未完成
-            impls.get( path )
+            impls.get( path ) match {
+                case None =>
+                    if( path.equals(NMPath.root) ) {
+                        None
+                    } else {
+                        find( NMPath.parent( path ) )
+                    }
+                case impl => impl
+            }
         }
+
         def withImpl[T] ( path : String,  f : NMTreeImplimentation => T ) : T = {
             ImplMap.find(path) match {
             case None =>
@@ -314,6 +327,10 @@
         ImplMap.withImpl( path.canonical, impl => impl.createStream( path ) )
     }
 
+    def createDir ( path : NMPath ) : Unit = {
+        ImplMap.withImpl( path.canonical, impl => impl.createDir( path ) )
+    }
+
     def createDescription ( path : NMPath ) : TDescriptionElement = {
         ImplMap.withImpl( path.canonical, impl => impl.createDescription( path ) )
     }
@@ -337,39 +354,40 @@
 
     def localCommit( ops : Seq[ NMTreeOperations ] ) : Unit = {
       try {
-	val id = 0 // <- 未実装
-	val treeOp =
-	  env.getProcessContext(id) match {
-	    case Some (c) => ImplMap.findSurely(c.currentDir).treeOp
-	    case None => return
-	  }
-	for (op <- ops) {
-	  op match {
-	    case Move(src, dst) => treeOp.move(src, dst)
-	    case Copy(src, dst, overwrite, recursive) =>
-	      treeOp.copy(src, dst, overwrite, recursive)
-	    case Delete(path, rec) =>
-	      treeOp.delete(path, rec)
-	    case SymLink(src, dst) =>
-	      treeOp.symLink(src, dst)
-	    case ChangePermission(src, p) =>
-	      treeOp.changePermission(src, p)
-	    case Update(src, rec) =>
-	      treeOp.update(src, rec)
-	    case Commit(src, rec) =>
-	      treeOp.commit(src, rec)
-	    case Revert(src) =>
-	      treeOp.revert(src)
-	    case Resolve(src) =>
-	      treeOp.resolve(src)
-	    case _ => println("other")
-	  }
-	}
+          for (op <- ops) {
+              op match {
+                  case Move(src, dst) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.move(src, dst)
+                  case Copy(src, dst, overwrite, recursive) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.copy(src, dst, overwrite, recursive)
+                  case Delete(path, rec) =>
+                      val treeOp = ImplMap.findSurely(path.canonical).treeOp
+                      treeOp.delete(path, rec)
+                  case ChangePermission(src, p) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.changePermission(src, p)
+                  case Update(src, rec) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.update(src, rec)
+                  case Commit(src, rec) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.commit(src, rec)
+                  case Revert(src) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.revert(src)
+                  case Resolve(src) =>
+                      val treeOp = ImplMap.findSurely(src.canonical).treeOp
+                      treeOp.resolve(src)
+                  case _ =>
+                      ()
+                      //println("dose not support operation")
+              }
+          }
+      } catch {
+          case _ => println("err");
       }
-      catch {
-	case _ => println("err");
-      }
-
     }
 
     def globalCommit( root : NMPath ) : Unit = {

Modified: trunk/source/NMTree/test/NMFileSystemTreeTest.scala
===================================================================
--- trunk/source/NMTree/test/NMFileSystemTreeTest.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/test/NMFileSystemTreeTest.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -24,28 +24,28 @@
     }
 
     def mkdir(path : String){
-    val file = new File(path)
-    file.mkdirs()
+        val file = new File(path)
+        file.mkdirs()
     }
 
     def touch(path : String, content : String){
         val output = new OutputStreamWriter(new FileOutputStream( path ))
-    output.write(content)
-    output.close()
+        output.write(content)
+        output.close()
     }
 
     override def beforeEach() {
-    mkdir( test_dir )
-    touch( test_dir + "foo.txt" , "123\n")
-    mkdir( test_dir + "bar" )
-    touch( test_dir + "bar/bar.txt", "" )
+        mkdir( test_dir )
+        touch( test_dir + "foo.txt" , "123\n")
+        mkdir( test_dir + "bar" )
+        touch( test_dir + "bar/bar.txt", "" )
 
-    (new File( test_dir + "foo.txt")).setLastModified( today.getTime() )
+        (new File( test_dir + "foo.txt")).setLastModified( today.getTime() )
     }
 
 
     override def afterEach()  {
-    rm_rf( test_dir )
+        rm_rf( test_dir )
     }
 
     val fs = new NMFileSystemTree( "./test/NMFileSystemTreeTest", "/" )
@@ -54,87 +54,89 @@
 
     // PathOperationsのテスト
     test( "パスが実際に存在するかの確認" ) {
-    assert (pathOp.exists("/foo.txt")    === true )
-    assert (pathOp.exists("/bar")        === true )
-    assert (pathOp.exists("/non-exists") === false)
+        assert (pathOp.exists("/foo.txt")    === true )
+        assert (pathOp.exists("/bar")        === true )
+        assert (pathOp.exists("/non-exists") === false)
     }
 
     test ( "パスがディレクトリかの確認" ) {
-    assert (pathOp.isNode("/foo.txt")    == false)
-    assert (pathOp.isNode("/bar")        == true)
-    assert (pathOp.isNode("/non-exists") == false)
+        assert (pathOp.isNode("/foo.txt")    == false)
+        assert (pathOp.isNode("/bar")        == true)
+        assert (pathOp.isNode("/non-exists") == false)
     }
 
     test ( "サブファイルの取得" ) {
-    assert (pathOp.children("/")    === List[NMPath]("/bar","/foo.txt"))
-    assert (pathOp.children("/bar") === List[NMPath]("/bar/bar.txt"))
+        assert (pathOp.children("/")    === List[NMPath]("/bar","/foo.txt"))
+        assert (pathOp.children("/bar") === List[NMPath]("/bar/bar.txt"))
     }
 
     test ( "ファイルの属性" ) {
-    val attr = pathOp.attribute( "/foo.txt" )
-    assert(attr.size === 4)
-    assert(attr.lastUpdateDate.toString() === today.toString())
-    assert(attr.versionStatus === Neutral)
+        val attr = pathOp.attribute( "/foo.txt" )
+        assert(attr.size === 4)
+        assert(attr.lastUpdateDate.toString() === today.toString())
+        assert(attr.versionStatus === Neutral)
     }
 
     test ( "権限" ) ( pending )
 
     test ( "バージョン" ) {
-    assert( pathOp.versionStatus( "/foo.txt" ) === Neutral )
+        assert( pathOp.versionStatus( "/foo.txt" ) === Neutral )
     }
 
     // tree operation
     test( "move" ) {
-    assert( pathOp.exists( "/foo.txt" )  === true  )
-    assert( pathOp.exists( "/foo2.txt" ) === false )
+        assert( pathOp.exists( "/foo.txt" )  === true  )
+        assert( pathOp.exists( "/foo2.txt" ) === false )
 
-    treeOp.move("/foo.txt","/foo2.txt")
+        treeOp.move("/foo.txt","/foo2.txt")
 
-    assert( pathOp.exists( "/foo.txt" )  === false )
-    assert( pathOp.exists( "/foo2.txt" ) === true  )
+        assert( pathOp.exists( "/foo.txt" )  === false )
+        assert( pathOp.exists( "/foo2.txt" ) === true  )
     }
 
     test( "copy-1" ) {
-    assert( pathOp.exists( "/foo.txt" )  === true  )
-    assert( pathOp.exists( "/foo2.txt" ) === false )
+        assert( pathOp.exists( "/foo.txt" )  === true  )
+        assert( pathOp.exists( "/foo2.txt" ) === false )
 
-    treeOp.copy("/foo.txt","/foo2.txt",false,false)
+        treeOp.copy("/foo.txt","/foo2.txt",false,false)
 
-    assert( pathOp.exists( "/foo.txt" )  === true )
-    assert( pathOp.exists( "/foo2.txt" ) === true )
+        assert( pathOp.exists( "/foo.txt" )  === true )
+        assert( pathOp.exists( "/foo2.txt" ) === true )
     }
 
     test( "copy-2" ) {
-    treeOp.copy("/foo.txt","/bar/bar.txt", false ,false)
-    assert( pathOp.attribute( "/bar/bar.txt" ).size === 0)
+        treeOp.copy("/foo.txt","/bar/bar.txt", false ,false)
+        assert( pathOp.attribute( "/bar/bar.txt" ).size === 0)
     }
 
     test ("copy-overwrite" ){
-    treeOp.copy("/foo.txt","/bar/bar.txt", true ,false)
-    assert( pathOp.attribute( "/bar/bar.txt" ).size === 4)
+        treeOp.copy("/foo.txt","/bar/bar.txt", true ,false)
+        assert( pathOp.attribute( "/bar/bar.txt" ).size === 4)
     }
 
     test( "copy-3" ) {
-    treeOp.copy("/bar","/baz",false,false)
-    assert( pathOp.exists( "/baz/bar.txt" )  === false )
+        treeOp.copy("/bar","/baz",false,false)
+        assert( pathOp.exists( "/baz/bar.txt" )  === false )
     }
 
     test( "copy-4") {
-    treeOp.copy("/bar","/baz",false,true)
-    assert( pathOp.exists( "/baz/bar.txt" )  === true  )
+        treeOp.copy("/bar","/baz",false,true)
+        assert( pathOp.exists( "/baz/bar.txt" )  === true  )
     }
 
     test( "delete-1" ) {
-    assert( pathOp.exists( "/foo.txt" )  === true  )
-    treeOp.delete( "/foo.txt",false )
-    assert( pathOp.exists( "/foo.txt" )  === false )
+        assert( pathOp.exists( "/foo.txt" )  === true  )
+        treeOp.delete( "/foo.txt", false )
+        assert( pathOp.exists( "/foo.txt" )  === false )
     }
 
     test( "delete-2" ) {
-    treeOp.delete( "/bar",false )
-    assert( pathOp.exists( "/bar" )  === true )
+        intercept[LowLevelException] {
+            treeOp.delete( "/bar",false )
+        }
+        assert( pathOp.exists( "/bar" )  === true )
 
-    treeOp.delete( "/bar",true )
-    assert( pathOp.exists( "/bar" )  === false )
+        treeOp.delete( "/bar",true )
+        assert( pathOp.exists( "/bar" )  === false )
     }
 }

Modified: trunk/source/NMTree/test/NMTreeBehavior.scala
===================================================================
--- trunk/source/NMTree/test/NMTreeBehavior.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/test/NMTreeBehavior.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -2,19 +2,49 @@
 
 import org.scalatest.FunSuite
 import org.scalatest.BeforeAndAfterEach
+import info.ngms.nmtree.NMTreeOperations
 
 trait NMTreeBehavior extends FunSuite {
     test("マウント") (pending)
     test("アンマウント") (pending)
-    test("ディレクトリの作成") (pending)
+    test("ディレクトリの作成") {
+        val path = new NMPath("/dir")
+        NMTree.createDir( path )
+        assert( path.exists === true )
+        assert( path.isDir === true )
+    }
     test("ディレクトリの削除") (pending)
     test("ディレクトリの移動") (pending)
     test("Tree実装をまたがるディレクトリの移動") (pending)
-    test("ファイルの作成") (pending)
-    test("ファイルの削除") (pending)
-    test("ファイルの移動") (pending)
+    test("ファイルの作成及び削除") {
+        val path = new NMPath("/willdelete")
+        val stream = NMTree.createStream(path)
+        assert ( path.exists === true )
+        stream.close // closeしないと削除に失敗する
+        NMTree.localCommit( List(Delete( path, false)) )
+        assert ( path.exists === false )
+    }
+    test("ファイルの移動") {
+        val src = new NMPath("/from")
+        val dst = new NMPath("/to")
+        val stream = NMTree.createStream(src)
+        stream.close
+        assert ( src.exists === true )
+        NMTree.localCommit( List(Move( src, dst)) )
+        assert ( src.exists === false )
+        assert ( dst.exists === true )
+    }
     test("Tree実装をまたがるファイルの移動") (pending)
-    test("ファイルのコピー") (pending)
+    test("ファイルのコピー") {
+        val src = new NMPath("/from2")
+        val dst = new NMPath("/to2")
+        val stream = NMTree.createStream(src)
+        stream.close
+        assert ( src.exists === true )
+        NMTree.localCommit( List(Copy( src, dst, false, false )) )
+        assert ( src.exists === true )
+        assert ( dst.exists === true )
+    }
     test("ファイルへの書き込み") (pending)
     test("ファイルからの読み込み") (pending)
     test("Descriptionファイルへの書き込み") (pending)

Modified: trunk/source/NMTree/test/NMTreeWithFileSystemTest.scala
===================================================================
--- trunk/source/NMTree/test/NMTreeWithFileSystemTest.scala	2009-12-17 02:41:39 UTC (rev 65)
+++ trunk/source/NMTree/test/NMTreeWithFileSystemTest.scala	2009-12-17 03:48:47 UTC (rev 66)
@@ -2,6 +2,7 @@
 
 import org.scalatest.FunSuite
 import org.scalatest.BeforeAndAfterEach
+import java.io._
 
 class NMTreeWithFileSystemTest extends FunSuite with BeforeAndAfterEach with NMTreeBehavior {
 
@@ -9,12 +10,31 @@
         new NMPath(path)
     }
 
+    def rm_rf(path : String) {
+        val file = new File(path)
+        if(file.isDirectory()){
+            file.listFiles.foreach(f => rm_rf(f.toString))
+            file.delete()
+        }else {
+            file.delete()
+        }
+    }
+
+    def mkdir(path : String){
+        val file = new File(path)
+        file.mkdirs()
+    }
+
+    val testdir = "./test/NMTreeTest/"
+
     override def beforeEach() {
-        val fs = new NMFileSystemTree( "c:/work", "/" )
+        mkdir( testdir )
+        val fs = new NMFileSystemTree( testdir, "/" )
         NMTree.mount( "/", fs )
     }
 
     override def afterEach()  {
         NMTree.unmount( "/" )
+        rm_rf(testdir)
     }
 }




Ngms-svn メーリングリストの案内
アーカイブの一覧に戻る