virtfs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +154 -0
  8. data/Rakefile +5 -0
  9. data/lib/virtfs-nativefs-thick.rb +1 -0
  10. data/lib/virtfs-nativefs-thin.rb +1 -0
  11. data/lib/virtfs.rb +38 -0
  12. data/lib/virtfs/activation.rb +97 -0
  13. data/lib/virtfs/block_io.rb +140 -0
  14. data/lib/virtfs/byte_range.rb +71 -0
  15. data/lib/virtfs/context.rb +300 -0
  16. data/lib/virtfs/context_manager.rb +175 -0
  17. data/lib/virtfs/context_switch_class_methods.rb +96 -0
  18. data/lib/virtfs/delegate_module.rb +40 -0
  19. data/lib/virtfs/dir_instance_delegate.rb +3 -0
  20. data/lib/virtfs/exception.rb +13 -0
  21. data/lib/virtfs/file_instance_delegate.rb +3 -0
  22. data/lib/virtfs/file_modes_and_options.rb +293 -0
  23. data/lib/virtfs/find_class_methods.rb +106 -0
  24. data/lib/virtfs/io_buffer.rb +133 -0
  25. data/lib/virtfs/io_instance_delegate.rb +3 -0
  26. data/lib/virtfs/kernel.rb +146 -0
  27. data/lib/virtfs/nativefs/thick.rb +30 -0
  28. data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
  29. data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
  30. data/lib/virtfs/nativefs/thin.rb +32 -0
  31. data/lib/virtfs/nativefs/thin/dir.rb +30 -0
  32. data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
  33. data/lib/virtfs/nativefs/thin/file.rb +112 -0
  34. data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
  35. data/lib/virtfs/protofs/protofs.rb +7 -0
  36. data/lib/virtfs/protofs/protofs_base.rb +12 -0
  37. data/lib/virtfs/protofs/protofs_dir.rb +13 -0
  38. data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
  39. data/lib/virtfs/protofs/protofs_file.rb +27 -0
  40. data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
  41. data/lib/virtfs/stat.rb +100 -0
  42. data/lib/virtfs/thin_dir_delegator.rb +79 -0
  43. data/lib/virtfs/thin_file_delegator.rb +77 -0
  44. data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
  45. data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
  46. data/lib/virtfs/v_dir.rb +238 -0
  47. data/lib/virtfs/v_file.rb +480 -0
  48. data/lib/virtfs/v_io.rb +243 -0
  49. data/lib/virtfs/v_pathname.rb +128 -0
  50. data/lib/virtfs/version.rb +3 -0
  51. data/spec/activate_spec.rb +202 -0
  52. data/spec/chroot_spec.rb +120 -0
  53. data/spec/context_manager_class_spec.rb +246 -0
  54. data/spec/context_manager_instance_spec.rb +255 -0
  55. data/spec/context_spec.rb +335 -0
  56. data/spec/data/UTF-16LE-data.txt +0 -0
  57. data/spec/data/UTF-8-data.txt +212 -0
  58. data/spec/dir_class_spec.rb +506 -0
  59. data/spec/dir_instance_spec.rb +208 -0
  60. data/spec/file_class_spec.rb +2106 -0
  61. data/spec/file_instance_spec.rb +154 -0
  62. data/spec/file_modes_and_options_spec.rb +1556 -0
  63. data/spec/find_spec.rb +142 -0
  64. data/spec/io_bufferio_size_shared_examples.rb +371 -0
  65. data/spec/io_bufferio_size_spec.rb +861 -0
  66. data/spec/io_bufferio_spec.rb +801 -0
  67. data/spec/io_class_spec.rb +145 -0
  68. data/spec/io_instance_spec.rb +516 -0
  69. data/spec/kernel_spec.rb +285 -0
  70. data/spec/mount_spec.rb +186 -0
  71. data/spec/nativefs_local_root_spec.rb +132 -0
  72. data/spec/path_spec.rb +39 -0
  73. data/spec/spec_helper.rb +126 -0
  74. data/tasks/rspec.rake +3 -0
  75. data/tasks/yard.rake +7 -0
  76. data/test/UTF-8-demo.txt +212 -0
  77. data/test/bench.rb +18 -0
  78. data/test/bio_internal_test.rb +45 -0
  79. data/test/delegate_io.rb +31 -0
  80. data/test/delegate_module.rb +62 -0
  81. data/test/encode_test.rb +42 -0
  82. data/test/enoent_test.rb +30 -0
  83. data/test/namespace_test.rb +42 -0
  84. data/test/read_block_valid_encoding.rb +44 -0
  85. data/test/read_test.rb +78 -0
  86. data/test/stream_readers.rb +46 -0
  87. data/test/utf-16-demo.txt +0 -0
  88. data/test/utf8_to_utf16.rb +77 -0
  89. data/test/wrapper_test.rb +34 -0
  90. data/virtfs.gemspec +29 -0
  91. metadata +230 -0
@@ -0,0 +1,335 @@
1
+ require 'spec_helper'
2
+
3
+ describe VirtFS::Context do
4
+ before(:all) do
5
+ @full_path = File.expand_path(__FILE__)
6
+ @rel_path = File.basename(@full_path)
7
+ @this_dir = File.dirname(@full_path)
8
+ @root = File::SEPARATOR
9
+
10
+ @new_root = VfsRealFile.expand_path(VfsRealFile.join(__dir__, ".."))
11
+ @new_this_dir = VfsRealFile.expand_path(VfsRealFile.join("/", VfsRealFile.basename(__dir__)))
12
+ @new_full_path = VfsRealFile.expand_path(VfsRealFile.join(@new_this_dir, VfsRealFile.basename(__FILE__)))
13
+ end
14
+
15
+ before(:each) do
16
+ reset_context
17
+ @context0 = VirtFS::Context.new
18
+ end
19
+
20
+ describe "#mount" do
21
+ before(:each) do
22
+ @native_fs = nativefs_class.new
23
+ end
24
+
25
+ context "single filesystem:" do
26
+ it "should raise RuntimeError when an invalid filesystem is provided" do
27
+ expect do
28
+ @context0.mount(nil, @root)
29
+ end.to raise_error(
30
+ RuntimeError, "mount: invalid filesystem object #{nil.class.name}"
31
+ )
32
+ end
33
+
34
+ it "should raise Errno::ENOENT when mount point doesn't exist" do
35
+ expect do
36
+ @context0.mount(@native_fs, @this_dir)
37
+ end.to raise_error(
38
+ Errno::ENOENT, "No such file or directory - #{@this_dir}"
39
+ )
40
+ end
41
+
42
+ it "should raise RuntimeError when attempting to reuse mount point" do
43
+ expect do
44
+ @context0.mount(@native_fs, @root)
45
+ @context0.mount(nativefs_class.new, @root)
46
+ end.to raise_error(
47
+ RuntimeError, "mount: mount point #{@root} is busy"
48
+ )
49
+ end
50
+
51
+ it "should raise RuntimeError when attempting to mount a mounted filesystem" do
52
+ expect do
53
+ @context0.mount(@native_fs, @root)
54
+ @context0.mount(@native_fs, @this_dir)
55
+ end.to raise_error(
56
+ RuntimeError, "mount: filesystem is busy"
57
+ )
58
+ end
59
+
60
+ it "should return nil on successful mount" do
61
+ expect(@context0.mount(@native_fs, @root)).to be_nil
62
+ end
63
+ end
64
+
65
+ context "second filesystem:" do
66
+ before(:each) do
67
+ @native_fs2 = nativefs_class.new
68
+ @context0.mount(@native_fs, @root)
69
+ end
70
+
71
+ it "should raise RuntimeError when attempting to reuse mount point" do
72
+ expect do
73
+ @context0.mount(@native_fs2, @this_dir)
74
+ @context0.mount(nativefs_class.new, @this_dir)
75
+ end.to raise_error(
76
+ RuntimeError, "mount: mount point #{@this_dir} is busy"
77
+ )
78
+ end
79
+
80
+ it "should return nil on successful mount" do
81
+ expect(@context0.mount(@native_fs2, @this_dir)).to be_nil
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#umount" do
87
+ before(:each) do
88
+ @native_fs = nativefs_class.new
89
+ end
90
+
91
+ it "should raise RuntimeError when nothing mounted on mount point" do
92
+ @context0.mount(@native_fs, @root)
93
+ expect do
94
+ @context0.umount(@this_dir)
95
+ end.to raise_error(
96
+ RuntimeError, "umount: nothing mounted on #{@this_dir}"
97
+ )
98
+ end
99
+
100
+ it "should return nil on successful umount" do
101
+ @context0.mount(@native_fs, @root)
102
+ expect(@context0.umount(@root)).to be_nil
103
+ end
104
+
105
+ it "should enable re-mount" do
106
+ @context0.mount(@native_fs, @root)
107
+ @context0.umount(@root)
108
+ expect(@context0.mount(@native_fs, @root)).to be_nil
109
+ end
110
+ end
111
+
112
+ describe "#mount_points" do
113
+ it "should return an Array" do
114
+ expect(@context0.mount_points).to be_kind_of(Array)
115
+ end
116
+
117
+ it "should return an empty Array when nothing mounted" do
118
+ expect(@context0.mount_points.empty?).to be true
119
+ end
120
+
121
+ it "should return an array of the expected length" do
122
+ expect(@context0.mount_points.length).to eq(0)
123
+ native_fs1 = nativefs_class.new
124
+ @context0.mount(native_fs1, @root)
125
+ expect(@context0.mount_points.length).to eq(1)
126
+ native_fs2 = nativefs_class.new
127
+ @context0.mount(native_fs2, @this_dir)
128
+ expect(@context0.mount_points.length).to eq(2)
129
+ end
130
+
131
+ it "should return an array containing expected values" do
132
+ expect(@context0.mount_points).to match_array([])
133
+ native_fs1 = nativefs_class.new
134
+ @context0.mount(native_fs1, @root)
135
+ expect(@context0.mount_points).to match_array([@root])
136
+ native_fs2 = nativefs_class.new
137
+ @context0.mount(native_fs2, @this_dir)
138
+ expect(@context0.mount_points).to match_array([@root, @this_dir])
139
+ end
140
+ end
141
+
142
+ describe "#mounted?" do
143
+ it "should return false when nothing is mounted" do
144
+ expect(@context0.mounted?(@root)).to be false
145
+ end
146
+
147
+ it "should return false, given a directory that's not a mount point" do
148
+ native_fs1 = nativefs_class.new
149
+ @context0.mount(native_fs1, @root)
150
+ expect(@context0.mounted?(@this_dir)).to be false
151
+ end
152
+
153
+ it "should return true, given a directory that is a mount point" do
154
+ native_fs1 = nativefs_class.new
155
+ @context0.mount(native_fs1, @root)
156
+ expect(@context0.mounted?(@root)).to be true
157
+ native_fs2 = nativefs_class.new
158
+ @context0.mount(native_fs2, @this_dir)
159
+ expect(@context0.mounted?(@this_dir)).to be true
160
+ end
161
+ end
162
+
163
+ describe "#fs_on" do
164
+ it "should return nil when nothing is mounted" do
165
+ expect(@context0.fs_on(@root)).to be nil
166
+ end
167
+
168
+ it "should return nil, given a directory that's not a mount point" do
169
+ native_fs1 = nativefs_class.new
170
+ @context0.mount(native_fs1, @root)
171
+ expect(@context0.fs_on(@this_dir)).to be nil
172
+ end
173
+
174
+ it "should return the FS object for the filesystem mounted on the mount point" do
175
+ native_fs1 = nativefs_class.new
176
+ @context0.mount(native_fs1, @root)
177
+ expect(@context0.fs_on(@root)).to eq(native_fs1)
178
+ native_fs2 = nativefs_class.new
179
+ @context0.mount(native_fs2, @this_dir)
180
+ expect(@context0.fs_on(@this_dir)).to eq(native_fs2)
181
+ end
182
+ end
183
+
184
+ describe "#chroot" do
185
+ before(:each) do
186
+ @native_fs = nativefs_class.new
187
+ @context0.mount(@native_fs, @root)
188
+ end
189
+
190
+ it "should raise Errno::ENOENT when directory does exist" do
191
+ expect do
192
+ @context0.chroot("/not_a_dir/foo.d")
193
+ end.to raise_error(
194
+ Errno::ENOENT, /No such file or directory/
195
+ )
196
+ end
197
+
198
+ it "should return 0 on success" do
199
+ expect(@context0.chroot(@this_dir)).to eq(0)
200
+ end
201
+
202
+ it "should set the value of root accordingly" do
203
+ @context0.chroot(@new_root)
204
+ _cwd, root = @context0.cwd_root
205
+ expect(root).to eq(@new_root)
206
+ end
207
+
208
+ it "should set the current directory to '/'" do
209
+ @context0.chroot(@new_root)
210
+ cwd, _root = @context0.cwd_root
211
+ expect(cwd).to eq(File::SEPARATOR)
212
+ end
213
+
214
+ it "should find directory through new full path" do
215
+ @context0.chroot(@new_root)
216
+ expect(@context0.dir_exist?(@new_this_dir)).to be true
217
+ end
218
+ end
219
+
220
+ describe "#with_root" do
221
+ before(:each) do
222
+ @native_fs = nativefs_class.new
223
+ @context0.mount(@native_fs, @root)
224
+ end
225
+
226
+ it "should raise Errno::ENOENT when directory does exist" do
227
+ expect do
228
+ @context0.with_root("/not_a_dir/foo.d") {}
229
+ end.to raise_error(
230
+ Errno::ENOENT, /No such file or directory/
231
+ )
232
+ end
233
+
234
+ it "should raise LocalJumpError when no block given" do
235
+ expect do
236
+ @context0.with_root(@this_dir)
237
+ end.to raise_error(
238
+ LocalJumpError, /no block given/
239
+ )
240
+ end
241
+
242
+ it "should set the value of root within the block" do
243
+ _cwd, root0 = @context0.cwd_root
244
+ expect(root0).to_not eq(@new_root)
245
+
246
+ @context0.with_root(@new_root) do
247
+ _cwd, root1 = @context0.cwd_root
248
+ expect(root1).to eq(@new_root)
249
+ end
250
+
251
+ _cwd, root2 = @context0.cwd_root
252
+ expect(root2).to eq(root0)
253
+ end
254
+ end
255
+
256
+ describe "#path_lookup" do
257
+ context "with no filesystems mounted" do
258
+ it "should raise Errno::ENOENT" do
259
+ expect do
260
+ @context0.path_lookup(@full_path)
261
+ end.to raise_error(
262
+ Errno::ENOENT, "No such file or directory - #{@full_path}"
263
+ )
264
+ end
265
+
266
+ it "should raise Errno::ENOENT with original path in message" do
267
+ expect do
268
+ @context0.path_lookup(@rel_path)
269
+ end.to raise_error(
270
+ Errno::ENOENT, "No such file or directory - #{@rel_path}"
271
+ )
272
+ end
273
+ end
274
+
275
+ context "with FS mounted on #{@root}" do
276
+ before(:each) do
277
+ @native_fs = nativefs_class.new
278
+ @context0.mount(@native_fs, @root)
279
+ end
280
+
281
+ it "should return native_fs, when given fully qualified path" do
282
+ fs, _path = @context0.path_lookup(@full_path)
283
+ expect(fs).to eq(@native_fs)
284
+ end
285
+
286
+ it "should return the full path, when given fully qualified path" do
287
+ _fs, path = @context0.path_lookup(@full_path)
288
+ expect(path).to eq(@full_path) # .sub(@native_fs.mount_point, '')
289
+ end
290
+
291
+ it "should return native_fs, when given relative path" do
292
+ @context0.chdir(@this_dir)
293
+ fs, _path = @context0.path_lookup(@rel_path)
294
+ expect(fs).to eq(@native_fs)
295
+ end
296
+
297
+ it "should return the full path, when given relative path" do
298
+ @context0.chdir(@this_dir)
299
+ _fs, path = @context0.path_lookup(@rel_path)
300
+ expect(path).to eq(@full_path) # .sub(@native_fs.mount_point, '')
301
+ end
302
+ end
303
+
304
+ context "with FS mounted on #{@this_dir}" do
305
+ before(:each) do
306
+ @native_fs = nativefs_class.new
307
+ @native_fs2 = nativefs_class.new
308
+ @context0.mount(@native_fs, @root)
309
+ @context0.mount(@native_fs2, @this_dir)
310
+ end
311
+
312
+ it "should return native_fs2, when given fully qualified path" do
313
+ fs, _path = @context0.path_lookup(@full_path)
314
+ expect(fs).to eq(@native_fs2)
315
+ end
316
+
317
+ it "should return the path relative to the mount point, when given fully qualified path" do
318
+ _fs, path = @context0.path_lookup(@full_path)
319
+ expect(path).to eq(@full_path.sub(@native_fs2.mount_point, File::SEPARATOR))
320
+ end
321
+
322
+ it "should return native_fs2, when given relative path" do
323
+ @context0.chdir(@this_dir)
324
+ fs, _path = @context0.path_lookup(@rel_path)
325
+ expect(fs).to eq(@native_fs2)
326
+ end
327
+
328
+ it "should return the path relative to the mount point, when given relative path" do
329
+ @context0.chdir(@this_dir)
330
+ _fs, path = @context0.path_lookup(@rel_path)
331
+ expect(path).to eq(@full_path.sub(@native_fs2.mount_point, File::SEPARATOR))
332
+ end
333
+ end
334
+ end
335
+ end
@@ -0,0 +1,212 @@
1
+
2
+ UTF-8 encoded sample plain-text file
3
+ ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
4
+
5
+ Markus Kuhn [ˈmaʳkʊs kuːn] <http://www.cl.cam.ac.uk/~mgk25/> — 2002-07-25 CC BY
6
+
7
+
8
+ The ASCII compatible UTF-8 encoding used in this plain-text file
9
+ is defined in Unicode, ISO 10646-1, and RFC 2279.
10
+
11
+
12
+ Using Unicode/UTF-8, you can write in emails and source code things such as
13
+
14
+ Mathematics and sciences:
15
+
16
+ ∮ E⋅da = Q, n → ∞, ∑ f(i) = ∏ g(i), ⎧⎡⎛┌─────┐⎞⎤⎫
17
+ ⎪⎢⎜│a²+b³ ⎟⎥⎪
18
+ ∀x∈ℝ: ⌈x⌉ = −⌊−x⌋, α ∧ ¬β = ¬(¬α ∨ β), ⎪⎢⎜│───── ⎟⎥⎪
19
+ ⎪⎢⎜⎷ c₈ ⎟⎥⎪
20
+ ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⎨⎢⎜ ⎟⎥⎬
21
+ ⎪⎢⎜ ∞ ⎟⎥⎪
22
+ ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (⟦A⟧ ⇔ ⟪B⟫), ⎪⎢⎜ ⎲ ⎟⎥⎪
23
+ ⎪⎢⎜ ⎳aⁱ-bⁱ⎟⎥⎪
24
+ 2H₂ + O₂ ⇌ 2H₂O, R = 4.7 kΩ, ⌀ 200 mm ⎩⎣⎝i=1 ⎠⎦⎭
25
+
26
+ Linguistics and dictionaries:
27
+
28
+ ði ıntəˈnæʃənəl fəˈnɛtık əsoʊsiˈeıʃn
29
+ Y [ˈʏpsilɔn], Yen [jɛn], Yoga [ˈjoːgɑ]
30
+
31
+ APL:
32
+
33
+ ((V⍳V)=⍳⍴V)/V←,V ⌷←⍳→⍴∆∇⊃‾⍎⍕⌈
34
+
35
+ Nicer typography in plain text files:
36
+
37
+ ╔══════════════════════════════════════════╗
38
+ ║ ║
39
+ ║ • ‘single’ and “double” quotes ║
40
+ ║ ║
41
+ ║ • Curly apostrophes: “We’ve been here” ║
42
+ ║ ║
43
+ ║ • Latin-1 apostrophe and accents: '´` ║
44
+ ║ ║
45
+ ║ • ‚deutsche‘ „Anführungszeichen“ ║
46
+ ║ ║
47
+ ║ • †, ‡, ‰, •, 3–4, —, −5/+5, ™, … ║
48
+ ║ ║
49
+ ║ • ASCII safety test: 1lI|, 0OD, 8B ║
50
+ ║ ╭─────────╮ ║
51
+ ║ • the euro symbol: │ 14.95 € │ ║
52
+ ║ ╰─────────╯ ║
53
+ ╚══════════════════════════════════════════╝
54
+
55
+ Combining characters:
56
+
57
+ STARGΛ̊TE SG-1, a = v̇ = r̈, a⃑ ⊥ b⃑
58
+
59
+ Greek (in Polytonic):
60
+
61
+ The Greek anthem:
62
+
63
+ Σὲ γνωρίζω ἀπὸ τὴν κόψη
64
+ τοῦ σπαθιοῦ τὴν τρομερή,
65
+ σὲ γνωρίζω ἀπὸ τὴν ὄψη
66
+ ποὺ μὲ βία μετράει τὴ γῆ.
67
+
68
+ ᾿Απ᾿ τὰ κόκκαλα βγαλμένη
69
+ τῶν ῾Ελλήνων τὰ ἱερά
70
+ καὶ σὰν πρῶτα ἀνδρειωμένη
71
+ χαῖρε, ὦ χαῖρε, ᾿Ελευθεριά!
72
+
73
+ From a speech of Demosthenes in the 4th century BC:
74
+
75
+ Οὐχὶ ταὐτὰ παρίσταταί μοι γιγνώσκειν, ὦ ἄνδρες ᾿Αθηναῖοι,
76
+ ὅταν τ᾿ εἰς τὰ πράγματα ἀποβλέψω καὶ ὅταν πρὸς τοὺς
77
+ λόγους οὓς ἀκούω· τοὺς μὲν γὰρ λόγους περὶ τοῦ
78
+ τιμωρήσασθαι Φίλιππον ὁρῶ γιγνομένους, τὰ δὲ πράγματ᾿
79
+ εἰς τοῦτο προήκοντα, ὥσθ᾿ ὅπως μὴ πεισόμεθ᾿ αὐτοὶ
80
+ πρότερον κακῶς σκέψασθαι δέον. οὐδέν οὖν ἄλλο μοι δοκοῦσιν
81
+ οἱ τὰ τοιαῦτα λέγοντες ἢ τὴν ὑπόθεσιν, περὶ ἧς βουλεύεσθαι,
82
+ οὐχὶ τὴν οὖσαν παριστάντες ὑμῖν ἁμαρτάνειν. ἐγὼ δέ, ὅτι μέν
83
+ ποτ᾿ ἐξῆν τῇ πόλει καὶ τὰ αὑτῆς ἔχειν ἀσφαλῶς καὶ Φίλιππον
84
+ τιμωρήσασθαι, καὶ μάλ᾿ ἀκριβῶς οἶδα· ἐπ᾿ ἐμοῦ γάρ, οὐ πάλαι
85
+ γέγονεν ταῦτ᾿ ἀμφότερα· νῦν μέντοι πέπεισμαι τοῦθ᾿ ἱκανὸν
86
+ προλαβεῖν ἡμῖν εἶναι τὴν πρώτην, ὅπως τοὺς συμμάχους
87
+ σώσομεν. ἐὰν γὰρ τοῦτο βεβαίως ὑπάρξῃ, τότε καὶ περὶ τοῦ
88
+ τίνα τιμωρήσεταί τις καὶ ὃν τρόπον ἐξέσται σκοπεῖν· πρὶν δὲ
89
+ τὴν ἀρχὴν ὀρθῶς ὑποθέσθαι, μάταιον ἡγοῦμαι περὶ τῆς
90
+ τελευτῆς ὁντινοῦν ποιεῖσθαι λόγον.
91
+
92
+ Δημοσθένους, Γ´ ᾿Ολυνθιακὸς
93
+
94
+ Georgian:
95
+
96
+ From a Unicode conference invitation:
97
+
98
+ გთხოვთ ახლავე გაიაროთ რეგისტრაცია Unicode-ის მეათე საერთაშორისო
99
+ კონფერენციაზე დასასწრებად, რომელიც გაიმართება 10-12 მარტს,
100
+ ქ. მაინცში, გერმანიაში. კონფერენცია შეჰკრებს ერთად მსოფლიოს
101
+ ექსპერტებს ისეთ დარგებში როგორიცაა ინტერნეტი და Unicode-ი,
102
+ ინტერნაციონალიზაცია და ლოკალიზაცია, Unicode-ის გამოყენება
103
+ ოპერაციულ სისტემებსა, და გამოყენებით პროგრამებში, შრიფტებში,
104
+ ტექსტების დამუშავებასა და მრავალენოვან კომპიუტერულ სისტემებში.
105
+
106
+ Russian:
107
+
108
+ From a Unicode conference invitation:
109
+
110
+ Зарегистрируйтесь сейчас на Десятую Международную Конференцию по
111
+ Unicode, которая состоится 10-12 марта 1997 года в Майнце в Германии.
112
+ Конференция соберет широкий круг экспертов по вопросам глобального
113
+ Интернета и Unicode, локализации и интернационализации, воплощению и
114
+ применению Unicode в различных операционных системах и программных
115
+ приложениях, шрифтах, верстке и многоязычных компьютерных системах.
116
+
117
+ Thai (UCS Level 2):
118
+
119
+ Excerpt from a poetry on The Romance of The Three Kingdoms (a Chinese
120
+ classic 'San Gua'):
121
+
122
+ [----------------------------|------------------------]
123
+ ๏ แผ่นดินฮั่นเสื่อมโทรมแสนสังเวช พระปกเกศกองบู๊กู้ขึ้นใหม่
124
+ สิบสองกษัตริย์ก่อนหน้าแลถัดไป สององค์ไซร้โง่เขลาเบาปัญญา
125
+ ทรงนับถือขันทีเป็นที่พึ่ง บ้านเมืองจึงวิปริตเป็นนักหนา
126
+ โฮจิ๋นเรียกทัพทั่วหัวเมืองมา หมายจะฆ่ามดชั่วตัวสำคัญ
127
+ เหมือนขับไสไล่เสือจากเคหา รับหมาป่าเข้ามาเลยอาสัญ
128
+ ฝ่ายอ้องอุ้นยุแยกให้แตกกัน ใช้สาวนั้นเป็นชนวนชื่นชวนใจ
129
+ พลันลิฉุยกุยกีกลับก่อเหตุ ช่างอาเพศจริงหนาฟ้าร้องไห้
130
+ ต้องรบราฆ่าฟันจนบรรลัย ฤๅหาใครค้ำชูกู้บรรลังก์ ฯ
131
+
132
+ (The above is a two-column text. If combining characters are handled
133
+ correctly, the lines of the second column should be aligned with the
134
+ | character above.)
135
+
136
+ Ethiopian:
137
+
138
+ Proverbs in the Amharic language:
139
+
140
+ ሰማይ አይታረስ ንጉሥ አይከሰስ።
141
+ ብላ ካለኝ እንደአባቴ በቆመጠኝ።
142
+ ጌጥ ያለቤቱ ቁምጥና ነው።
143
+ ደሀ በሕልሙ ቅቤ ባይጠጣ ንጣት በገደለው።
144
+ የአፍ ወለምታ በቅቤ አይታሽም።
145
+ አይጥ በበላ ዳዋ ተመታ።
146
+ ሲተረጉሙ ይደረግሙ።
147
+ ቀስ በቀስ፥ ዕንቁላል በእግሩ ይሄዳል።
148
+ ድር ቢያብር አንበሳ ያስር።
149
+ ሰው እንደቤቱ እንጅ እንደ ጉረቤቱ አይተዳደርም።
150
+ እግዜር የከፈተውን ጉሮሮ ሳይዘጋው አይድርም።
151
+ የጎረቤት ሌባ፥ ቢያዩት ይስቅ ባያዩት ያጠልቅ።
152
+ ሥራ ከመፍታት ልጄን ላፋታት።
153
+ ዓባይ ማደሪያ የለው፥ ግንድ ይዞ ይዞራል።
154
+ የእስላም አገሩ መካ የአሞራ አገሩ ዋርካ።
155
+ ተንጋሎ ቢተፉ ተመልሶ ባፉ።
156
+ ወዳጅህ ማር ቢሆን ጨርስህ አትላሰው።
157
+ እግርህን በፍራሽህ ልክ ዘርጋ።
158
+
159
+ Runes:
160
+
161
+ ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ
162
+
163
+ (Old English, which transcribed into Latin reads 'He cwaeth that he
164
+ bude thaem lande northweardum with tha Westsae.' and means 'He said
165
+ that he lived in the northern land near the Western Sea.')
166
+
167
+ Braille:
168
+
169
+ ⡌⠁⠧⠑ ⠼⠁⠒ ⡍⠜⠇⠑⠹⠰⠎ ⡣⠕⠌
170
+
171
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠙⠑⠁⠙⠒ ⠞⠕ ⠃⠑⠛⠔ ⠺⠊⠹⠲ ⡹⠻⠑ ⠊⠎ ⠝⠕ ⠙⠳⠃⠞
172
+ ⠱⠁⠞⠑⠧⠻ ⠁⠃⠳⠞ ⠹⠁⠞⠲ ⡹⠑ ⠗⠑⠛⠊⠌⠻ ⠕⠋ ⠙⠊⠎ ⠃⠥⠗⠊⠁⠇ ⠺⠁⠎
173
+ ⠎⠊⠛⠝⠫ ⠃⠹ ⠹⠑ ⠊⠇⠻⠛⠹⠍⠁⠝⠂ ⠹⠑ ⠊⠇⠻⠅⠂ ⠹⠑ ⠥⠝⠙⠻⠞⠁⠅⠻⠂
174
+ ⠁⠝⠙ ⠹⠑ ⠡⠊⠑⠋ ⠍⠳⠗⠝⠻⠲ ⡎⠊⠗⠕⠕⠛⠑ ⠎⠊⠛⠝⠫ ⠊⠞⠲ ⡁⠝⠙
175
+ ⡎⠊⠗⠕⠕⠛⠑⠰⠎ ⠝⠁⠍⠑ ⠺⠁⠎ ⠛⠕⠕⠙ ⠥⠏⠕⠝ ⠰⡡⠁⠝⠛⠑⠂ ⠋⠕⠗ ⠁⠝⠹⠹⠔⠛ ⠙⠑
176
+ ⠡⠕⠎⠑ ⠞⠕ ⠏⠥⠞ ⠙⠊⠎ ⠙⠁⠝⠙ ⠞⠕⠲
177
+
178
+ ⡕⠇⠙ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
179
+
180
+ ⡍⠔⠙⠖ ⡊ ⠙⠕⠝⠰⠞ ⠍⠑⠁⠝ ⠞⠕ ⠎⠁⠹ ⠹⠁⠞ ⡊ ⠅⠝⠪⠂ ⠕⠋ ⠍⠹
181
+ ⠪⠝ ⠅⠝⠪⠇⠫⠛⠑⠂ ⠱⠁⠞ ⠹⠻⠑ ⠊⠎ ⠏⠜⠞⠊⠊⠥⠇⠜⠇⠹ ⠙⠑⠁⠙ ⠁⠃⠳⠞
182
+ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲ ⡊ ⠍⠊⠣⠞ ⠙⠁⠧⠑ ⠃⠑⠲ ⠔⠊⠇⠔⠫⠂ ⠍⠹⠎⠑⠇⠋⠂ ⠞⠕
183
+ ⠗⠑⠛⠜⠙ ⠁ ⠊⠕⠋⠋⠔⠤⠝⠁⠊⠇ ⠁⠎ ⠹⠑ ⠙⠑⠁⠙⠑⠌ ⠏⠊⠑⠊⠑ ⠕⠋ ⠊⠗⠕⠝⠍⠕⠝⠛⠻⠹
184
+ ⠔ ⠹⠑ ⠞⠗⠁⠙⠑⠲ ⡃⠥⠞ ⠹⠑ ⠺⠊⠎⠙⠕⠍ ⠕⠋ ⠳⠗ ⠁⠝⠊⠑⠌⠕⠗⠎
185
+ ⠊⠎ ⠔ ⠹⠑ ⠎⠊⠍⠊⠇⠑⠆ ⠁⠝⠙ ⠍⠹ ⠥⠝⠙⠁⠇⠇⠪⠫ ⠙⠁⠝⠙⠎
186
+ ⠩⠁⠇⠇ ⠝⠕⠞ ⠙⠊⠌⠥⠗⠃ ⠊⠞⠂ ⠕⠗ ⠹⠑ ⡊⠳⠝⠞⠗⠹⠰⠎ ⠙⠕⠝⠑ ⠋⠕⠗⠲ ⡹⠳
187
+ ⠺⠊⠇⠇ ⠹⠻⠑⠋⠕⠗⠑ ⠏⠻⠍⠊⠞ ⠍⠑ ⠞⠕ ⠗⠑⠏⠑⠁⠞⠂ ⠑⠍⠏⠙⠁⠞⠊⠊⠁⠇⠇⠹⠂ ⠹⠁⠞
188
+ ⡍⠜⠇⠑⠹ ⠺⠁⠎ ⠁⠎ ⠙⠑⠁⠙ ⠁⠎ ⠁ ⠙⠕⠕⠗⠤⠝⠁⠊⠇⠲
189
+
190
+ (The first couple of paragraphs of "A Christmas Carol" by Dickens)
191
+
192
+ Compact font selection example text:
193
+
194
+ ABCDEFGHIJKLMNOPQRSTUVWXYZ /0123456789
195
+ abcdefghijklmnopqrstuvwxyz £©µÀÆÖÞßéöÿ
196
+ –—‘“”„†•…‰™œŠŸž€ ΑΒΓΔΩαβγδω АБВГДабвгд
197
+ ∀∂∈ℝ∧∪≡∞ ↑↗↨↻⇣ ┐┼╔╘░►☺♀ fi�⑀₂ἠḂӥẄɐː⍎אԱა
198
+
199
+ Greetings in various languages:
200
+
201
+ Hello world, Καλημέρα κόσμε, コンニチハ
202
+
203
+ Box drawing alignment tests: █
204
+
205
+ ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳
206
+ ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳
207
+ ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳
208
+ ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳
209
+ ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎
210
+ ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏
211
+ ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ ▗▄▖▛▀▜ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█
212
+ ▝▀▘▙▄▟