sekka 1.7.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -107,11 +107,11 @@
107
107
  okuri-nashi-list
108
108
  hiragana-phrase-list)))
109
109
 
110
- (let1 progress (if displayProgress
110
+ (let1 progress1 (if displayProgress
111
111
  (ProgressBar.create (alist->hash-table
112
112
  `(
113
- [title . "trie-tree "]
114
- [total . ,(* 2 (length keylist))]
113
+ [title . "trie-tree(1)"]
114
+ [total . ,(length keylist)]
115
115
  [output . ,STDERR]
116
116
  [format . ,progressbar-format]
117
117
  )))
@@ -119,7 +119,7 @@
119
119
  (receive (okuri-ari-list
120
120
  okuri-nashi-list
121
121
  hiragana-phrase-list)
122
- (grouping-keylist keylist progress)
122
+ (grouping-keylist keylist progress1)
123
123
 
124
124
  (let1 okuri-nashi-reverse-list
125
125
  (filter-map
@@ -129,32 +129,38 @@
129
129
  (str.reverse)))
130
130
  okuri-nashi-list)
131
131
 
132
- (when progress
133
- (progress.progress= (+ (length keylist)
134
- (- (length keylist)
135
- (+
136
- (length okuri-ari-list)
137
- (length okuri-nashi-list)
138
- (length okuri-nashi-reverse-list)
139
- (length hiragana-phrase-list))))))
140
- (set! keylist '()) ;; free memory
132
+ (let1 progress2
133
+ (if displayProgress
134
+ (ProgressBar.create (alist->hash-table
135
+ `(
136
+ [title . "trie-tree(2)"]
137
+ [total . ,(+
138
+ (length okuri-ari-list)
139
+ (length okuri-nashi-list)
140
+ (length okuri-nashi-reverse-list)
141
+ (length hiragana-phrase-list))]
142
+ [output . ,STDERR]
143
+ [format . ,progressbar-format]
144
+ )))
145
+ #f)
146
+ (set! keylist '()) ;; free memory
141
147
 
142
- (let1 trie (DistributedTrie::Trie.new kvs (+ okuri-ari-prefix ":" userid ":"))
143
- (trie-add-autocommit trie okuri-ari-list progress))
144
- (set! okuri-ari-list '()) ;; free memory
145
-
146
- (let1 trie (DistributedTrie::Trie.new kvs (+ okuri-nashi-prefix ":" userid ":"))
147
- (trie-add-autocommit trie okuri-nashi-list progress))
148
- (set! okuri-nashi-list '()) ;; free memory
149
-
150
- (let1 trie (DistributedTrie::Trie.new kvs (+ okuri-nashi-reverse-prefix ":" userid ":"))
151
- (trie-add-autocommit trie okuri-nashi-reverse-list progress))
152
- (set! okuri-nashi-reverse-list '()) ;; free memory
153
-
154
- (let1 trie (DistributedTrie::Trie.new kvs (+ hiragana-phrase-prefix ":" userid ":"))
155
- (trie-add-autocommit trie hiragana-phrase-list progress))
156
- (set! hiragana-phrase-list '()) ;; free memory
157
- ))))
148
+ (let1 trie (DistributedTrie::Trie.new kvs (+ okuri-ari-prefix ":" userid ":"))
149
+ (trie-add-autocommit trie okuri-ari-list progress2))
150
+ (set! okuri-ari-list '()) ;; free memory
151
+
152
+ (let1 trie (DistributedTrie::Trie.new kvs (+ okuri-nashi-prefix ":" userid ":"))
153
+ (trie-add-autocommit trie okuri-nashi-list progress2))
154
+ (set! okuri-nashi-list '()) ;; free memory
155
+
156
+ (let1 trie (DistributedTrie::Trie.new kvs (+ okuri-nashi-reverse-prefix ":" userid ":"))
157
+ (trie-add-autocommit trie okuri-nashi-reverse-list progress2))
158
+ (set! okuri-nashi-reverse-list '()) ;; free memory
159
+
160
+ (let1 trie (DistributedTrie::Trie.new kvs (+ hiragana-phrase-prefix ":" userid ":"))
161
+ (trie-add-autocommit trie hiragana-phrase-list progress2))
162
+ (set! hiragana-phrase-list '()) ;; free memory
163
+ )))))
158
164
 
159
165
  (define (append-entry userid kvs _key value)
160
166
  (let1 key (+ userid ":" _key)
@@ -193,7 +199,7 @@
193
199
  (define (create-keylist kvs f)
194
200
  (let1 progress (ProgressBar.create (alist->hash-table
195
201
  `(
196
- [title . "data-body "]
202
+ [title . "data-body "]
197
203
  [total . ,(file-length f)]
198
204
  [output . ,STDERR]
199
205
  [format . ,progressbar-format]
@@ -0,0 +1,113 @@
1
+ # jruby_mapdb.rb - "wrapper library for MapDB(java)"
2
+ #
3
+ # Copyright (c) 2017 Kiyoka Nishiyama <kiyoka@sumibi.org>
4
+ #
5
+ # Redistribution and use in source and binary forms, with or without
6
+ # modification, are permitted provided that the following conditions
7
+ # are met:
8
+ #
9
+ # 1. Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ #
12
+ # 2. Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # 3. Neither the name of the authors nor the names of its contributors
17
+ # may be used to endorse or promote products derived from this
18
+ # software without specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
26
+ # TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ #
32
+ #
33
+ jarpath = File.expand_path('../jar', __FILE__) + '/'
34
+
35
+ require jarpath + 'guava-19.0.jar'
36
+ require jarpath + 'elsa-3.0.0-M7.jar'
37
+ require jarpath + 'kotlin-stdlib-jre8-1.1.2-3.jar'
38
+ require jarpath + 'kotlin-compiler-1.1.2-3.jar'
39
+ require jarpath + 'google-collections-1.0.jar'
40
+ require jarpath + 'eclipse-collections-8.2.0.jar'
41
+ require jarpath + 'eclipse-collections-api-8.2.0.jar'
42
+ require jarpath + 'lz4-1.3.0.jar'
43
+ require jarpath + 'mapdb-3.1.0-SNAPSHOT.jar'
44
+
45
+ module OrgMapdb
46
+ include_package "org.mapdb"
47
+ end
48
+
49
+ module MapDB
50
+ class Tree
51
+ def initialize(treeobj)
52
+ @treeobj = treeobj
53
+ end
54
+ def keys
55
+ @treeobj.key_set.to_a
56
+ end
57
+ def put(key,value)
58
+ @treeobj.put(key,value)
59
+ end
60
+ def set(key,value)
61
+ put(key,value)
62
+ end
63
+ def get(key)
64
+ @treeobj.get(key)
65
+ end
66
+ def delete(key)
67
+ @treeobj.remove(key)
68
+ end
69
+ def clear
70
+ @treeobj.clear
71
+ end
72
+ def close
73
+ #nothing to do
74
+ end
75
+ end
76
+
77
+ class DB
78
+ attr_reader :mapdb, :type
79
+ def initialize(dbname=nil,treename=nil)
80
+ @tree = nil
81
+ if dbname.nil?
82
+ @type = :MemoryDB
83
+ @mapdb = OrgMapdb::DBMaker.
84
+ memoryDB().
85
+ closeOnJvmShutdown().
86
+ make()
87
+ else
88
+ @type = :FileDB
89
+ @mapdb = OrgMapdb::DBMaker.
90
+ fileDB(Java::JavaIo::File.new("#{dbname}")).
91
+ fileMmapEnableIfSupported().
92
+ closeOnJvmShutdown().
93
+ make()
94
+ end
95
+ if treename.nil?
96
+ raise ArgumentError("require treename.")
97
+ end
98
+ tree = @mapdb.treeMap("#{treename}").
99
+ keySerializer(OrgMapdb::Serializer.STRING).
100
+ valueSerializer(OrgMapdb::Serializer.STRING).
101
+ createOrOpen()
102
+ @tree = MapDB::Tree.new(tree)
103
+ end
104
+
105
+ def getTree()
106
+ return @tree
107
+ end
108
+
109
+ def close
110
+ @mapdb.close
111
+ end
112
+ end
113
+ end
@@ -63,6 +63,13 @@ class Kvs
63
63
  @leveldbFlag = false
64
64
  end
65
65
 
66
+ @mapdbFlag = true
67
+ begin
68
+ require 'sekka/jruby_mapdb'
69
+ rescue LoadError
70
+ @mapdbFlag = false
71
+ end
72
+
66
73
  @dbtype = dbtype
67
74
  case dbtype
68
75
  when :tokyocabinet
@@ -94,6 +101,13 @@ class Kvs
94
101
  raise RuntimeError, "Kvs.new() missed require( 'leveldb' )."
95
102
  end
96
103
 
104
+ when :mapdb
105
+ if @mapdbFlag
106
+ # do nothing
107
+ else
108
+ raise RuntimeError, "Kvs.new() missed require( 'sekka/jruby_mapdb' )."
109
+ end
110
+
97
111
  when :pure
98
112
  # do nothing
99
113
  else
@@ -121,6 +135,9 @@ class Kvs
121
135
  name = name + ".ldb"
122
136
  end
123
137
  @db = LevelDB::DB.new name
138
+ when :mapdb
139
+ @basedb = MapDB::DB.new(name,"sekka")
140
+ @db = @basedb.getTree
124
141
  when :pure
125
142
  @name = name
126
143
  if File.exist?( @name )
@@ -160,6 +177,8 @@ class Kvs
160
177
  @db[ key.force_encoding("ASCII-8BIT") ] = value.force_encoding("ASCII-8BIT")
161
178
  when :memcache
162
179
  @db.set( key.force_encoding("ASCII-8BIT"), value.force_encoding("ASCII-8BIT"), timeout )
180
+ when :mapdb
181
+ @db.set( key, value )
163
182
  when :pure
164
183
  @db[ key ] = value
165
184
  else
@@ -177,6 +196,8 @@ class Kvs
177
196
  case @dbtype
178
197
  when :memcache
179
198
  val = @db.get(key.force_encoding("ASCII-8BIT"))
199
+ when :mapdb
200
+ val = @db.get(key)
180
201
  else
181
202
  val = @db[ key ]
182
203
  end
@@ -200,7 +221,7 @@ class Kvs
200
221
 
201
222
  def clear()
202
223
  case @dbtype
203
- when :tokyocabinet, :gdbm, :pure
224
+ when :tokyocabinet, :gdbm, :pure, :mapdb
204
225
  @db.clear
205
226
  when :leveldb
206
227
  @db.clear!
@@ -216,7 +237,7 @@ class Kvs
216
237
  # return array of key string
217
238
  def keys()
218
239
  case @dbtype
219
- when :tokyocabinet, :gdbm, :redis
240
+ when :tokyocabinet, :gdbm, :redis, :mapdb
220
241
  @db.keys.map { |k|
221
242
  k.force_encoding("UTF-8")
222
243
  }
@@ -241,7 +262,7 @@ class Kvs
241
262
  }
242
263
  when :memcache
243
264
  raise RuntimeError, "Kvs#forward_match_keys method was not implemented for memcache."
244
- when :gdbm, :leveldb, :pure
265
+ when :gdbm, :leveldb, :pure, :mapdb
245
266
  self.keys( ).select {|key|
246
267
  key.match( "^" + prefix )
247
268
  }
@@ -256,6 +277,8 @@ class Kvs
256
277
  @db.close
257
278
  when :memcache, :redis
258
279
  # do nothing
280
+ when :mapdb
281
+ @basedb.close
259
282
  when :pure
260
283
  File.open( @name, "w" ) { |f|
261
284
  f.print( @db )
@@ -1,4 +1,4 @@
1
1
  class SekkaVersion
2
- def self.version() "1.7.0" end
2
+ def self.version() "1.7.1" end
3
3
  def self.dictVersion() "1.6.2" end
4
4
  end
@@ -0,0 +1 @@
1
+ 5c84a1697656a8e05153c87dcb7c0371 SEKKA-JISYO-1.6.2.N.mapdb
@@ -0,0 +1 @@
1
+ https://s3-ap-northeast-1.amazonaws.com/sekkadict/1.6.2/SEKKA-JISYO-1.6.2.N.mapdb
@@ -0,0 +1,82 @@
1
+ ;;-*- mode: nendo; syntax: scheme -*-
2
+ ;;;
3
+ ;;; downloader.nnd - downloaderライブラリのテスト
4
+ ;;;
5
+ ;;; Copyright (c) 2017 Kiyoka Nishiyama <kiyoka@sumibi.org>
6
+ ;;;
7
+ ;;; Redistribution and use in source and binary forms, with or without
8
+ ;;; modification, are permitted provided that the following conditions
9
+ ;;; are met:
10
+ ;;;
11
+ ;;; 1. Redistributions of source code must retain the above copyright
12
+ ;;; notice, this list of conditions and the following disclaimer.
13
+ ;;;
14
+ ;;; 2. Redistributions in binary form must reproduce the above copyright
15
+ ;;; notice, this list of conditions and the following disclaimer in the
16
+ ;;; documentation and/or other materials provided with the distribution.
17
+ ;;;
18
+ ;;; 3. Neither the name of the authors nor the names of its contributors
19
+ ;;; may be used to endorse or promote products derived from this
20
+ ;;; software without specific prior written permission.
21
+ ;;;
22
+ ;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ ;;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ ;;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ ;;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
+ ;;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ ;;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28
+ ;;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29
+ ;;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
+ ;;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
+ ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
+ ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ ;;;
34
+ ;;; $Id:
35
+ ;;;
36
+ (require "sekka/downloader")
37
+ (use nendo.test)
38
+ (load "./test/common.nnd")
39
+
40
+ (test-start "Downloader")
41
+ ;;===================================================================
42
+
43
+ ;;-------------------------------------------------------------------
44
+ (test-section "download textfile")
45
+
46
+ (test* "download md5"
47
+ 65
48
+ (let1 dl (Downloader.new "https://raw.githubusercontent.com/kiyoka/sekka/master/public_dict/1.6.2/SEKKA-JISYO-1.6.2.N.md5")
49
+ (dl.download)
50
+ (dl.getBodySize)))
51
+
52
+ (test* "download md5"
53
+ "./data/SEKKA-JISYO-1.6.2.N.tsv"
54
+ (let1 dl (Downloader.new "https://raw.githubusercontent.com/kiyoka/sekka/master/public_dict/1.6.2/SEKKA-JISYO-1.6.2.N.md5")
55
+ (dl.download)
56
+ (cadr (to-list (. (dl.getBody) split #/[ \n]+/)))))
57
+
58
+ (when #f
59
+ (test* "download tsv"
60
+ 196089257
61
+ (let1 dl (Downloader.new "https://s3-ap-northeast-1.amazonaws.com/sekkadict/1.6.2/SEKKA-JISYO-1.6.2.N.tsv" "/tmp/")
62
+ (dl.download)
63
+ (dl.saveAs "/tmp/t.tsv")
64
+ (dl.getBodySize))))
65
+
66
+ (test* "calc md5"
67
+ "611ed4eed5d5b4ed23cc06ca18944d74"
68
+ (let1 dl (Downloader.new "https://raw.githubusercontent.com/kiyoka/sekka/master/public_dict/1.6.2/SEKKA-JISYO-1.6.2.N.md5")
69
+ (dl.download)
70
+ (dl.calcMD5)))
71
+
72
+ (test* "download to file"
73
+ "c93df55bb4034c353d6aa8b40734329f ./data/SEKKA-JISYO-1.6.2.N.tsv"
74
+ (let1 dl (Downloader.new "https://raw.githubusercontent.com/kiyoka/sekka/master/public_dict/1.6.2/SEKKA-JISYO-1.6.2.N.md5")
75
+ (dl.downloadToFile "/tmp/md5.txt")
76
+ (with-open "/tmp/md5.txt"
77
+ (lambda (f)
78
+ (f.read.chomp)))))
79
+
80
+ ;;===================================================================
81
+
82
+ (test-end)
@@ -60,6 +60,8 @@
60
60
  (set! target "./test.dump"))
61
61
  ((eq? dbtype 'leveldb)
62
62
  (set! target "./test.ldb"))
63
+ ((eq? dbtype 'mapdb)
64
+ (set! target "./test2.mapdb"))
63
65
  ((eq? dbtype 'memcache)
64
66
  (error "memcached interface is obsolute."))
65
67
  (else
@@ -152,6 +154,8 @@
152
154
  (kvs.open target))
153
155
  ((eq? dbtype 'leveldb)
154
156
  (kvs.open target))
157
+ ((eq? dbtype 'mapdb)
158
+ (kvs.open target))
155
159
  ((eq? dbtype 'memcache)
156
160
  (error "memcached interface is obsolute."))
157
161
  (else
@@ -0,0 +1,105 @@
1
+ ;;-*- mode: nendo; syntax: scheme -*-
2
+ ;;;
3
+ ;;; jruby_mapdb.nnd - jruby_mapdbライブラリのテスト
4
+ ;;;
5
+ ;;; Copyright (c) 2017 Kiyoka Nishiyama <kiyoka@sumibi.org>
6
+ ;;;
7
+ ;;; Redistribution and use in source and binary forms, with or without
8
+ ;;; modification, are permitted provided that the following conditions
9
+ ;;; are met:
10
+ ;;;
11
+ ;;; 1. Redistributions of source code must retain the above copyright
12
+ ;;; notice, this list of conditions and the following disclaimer.
13
+ ;;;
14
+ ;;; 2. Redistributions in binary form must reproduce the above copyright
15
+ ;;; notice, this list of conditions and the following disclaimer in the
16
+ ;;; documentation and/or other materials provided with the distribution.
17
+ ;;;
18
+ ;;; 3. Neither the name of the authors nor the names of its contributors
19
+ ;;; may be used to endorse or promote products derived from this
20
+ ;;; software without specific prior written permission.
21
+ ;;;
22
+ ;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23
+ ;;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24
+ ;;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25
+ ;;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26
+ ;;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27
+ ;;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
28
+ ;;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29
+ ;;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30
+ ;;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31
+ ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32
+ ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ ;;;
34
+ ;;; $Id:
35
+ ;;;
36
+ (require "sekka/jruby_mapdb")
37
+ (use nendo.test)
38
+ (load "./test/common.nnd")
39
+
40
+ (test-start "MapDB (only Java)")
41
+ ;;===================================================================
42
+
43
+ ;;-------------------------------------------------------------------
44
+ (test-section "DB access")
45
+
46
+ (define db #f)
47
+ (define tree #f)
48
+
49
+ (set! db (MapDB::DB.new "test1.mapdb" "sekka1"))
50
+ (test* "db open"
51
+ "val1"
52
+ (let1 tree (db.getTree)
53
+ (tree.put "key1" "val1")
54
+ (tree.get "key1")))
55
+ (db.close)
56
+
57
+ (set! db (MapDB::DB.new "test1.mapdb" "sekka2"))
58
+ (test* "db put & get"
59
+ "val1val2val3"
60
+ (begin
61
+ (let1 tree (db.getTree)
62
+ (tree.put "key1" "val1")
63
+ (tree.put "key2" "val2")
64
+ (tree.put "key3" "val3")
65
+ (+ (tree.get "key1")
66
+ (tree.get "key2")
67
+ (tree.get "key3")))))
68
+ (db.close)
69
+
70
+ (set! db (MapDB::DB.new "test1.mapdb" "sekka3"))
71
+ (test* "db keys"
72
+ '("key1" "key2" "key3" "key4")
73
+ (begin
74
+ (let1 tree (db.getTree)
75
+ (tree.put "key1" "1")
76
+ (tree.put "key2" "2")
77
+ (tree.put "key3" "3")
78
+ (tree.put "key4" "4")
79
+ (to-list (tree.keys)))))
80
+
81
+ (test* "db delete"
82
+ '("key1" "key2" "key4")
83
+ (begin
84
+ (let1 tree (db.getTree)
85
+ (tree.delete "key3")
86
+ (to-list (tree.keys)))))
87
+
88
+ (test* "db put kanji"
89
+ "まじぱねぇ /マジパネェ/"
90
+ (begin
91
+ (let1 tree (db.getTree)
92
+ (tree.put "M:i;chi" "Cいっち")
93
+ (tree.get "M:i;chi")
94
+ (tree.put "M:かに" "/蟹/可児/蠏")
95
+ (tree.get "M:かに")
96
+ (tree.put "dummy:(stored)" "まじぱねぇ /マジパネェ/")
97
+ (tree.get "dummy:(stored)")
98
+ )))
99
+
100
+ (db.close)
101
+
102
+ ;;===================================================================
103
+
104
+
105
+ (test-end)