lenc 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/lenc/encr.rb +1 -0
- data/lib/lenc/repo.rb +28 -13
- metadata +2 -3
- data/lib/lenc/_OLD_tools.rb +0 -628
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0599074c2a147d12b565284ba7d57126d1e4fda4
|
4
|
+
data.tar.gz: b78817f171113983d8c7a412191d4b78b1683045
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f19660e7bdde1ffb36153dd0947dbd9bfd66e3f05c71610a5ab4b5f9db931fd34ab57421c901bd77d54a7d5b9a80c6f53fcd71f24c46bc24a503dc56125ca911
|
7
|
+
data.tar.gz: d8c08ff48b5ea0deaf6d565e29d702e85b0a6625fb09fcbf1d578d3997f20f6dce0f619dc0e2f45c1942254da2ec1bd7b6d4ab6d47bfe59bb49264024917183f
|
data/lib/lenc/encr.rb
CHANGED
@@ -15,6 +15,7 @@ class EncrApp
|
|
15
15
|
opt :verbose,"verbose operation"
|
16
16
|
opt :where, "specify source directory (default = current directory)", :type => :strings
|
17
17
|
opt :quiet, "quiet operation"
|
18
|
+
opt :dryrun, "show which files will be modified, but make no changes"
|
18
19
|
end
|
19
20
|
|
20
21
|
options = Trollop::with_standard_exception_handling p do
|
data/lib/lenc/repo.rb
CHANGED
@@ -69,9 +69,13 @@ module LEnc
|
|
69
69
|
end
|
70
70
|
|
71
71
|
|
72
|
+
# We now ignore 'dot-underscore' files which OSX seems to create sometimes
|
73
|
+
# to store additional information about other files.
|
74
|
+
|
72
75
|
DEFAULTIGNORE = \
|
73
76
|
"#{LENC_REPO_FILENAME}\n " \
|
74
77
|
".DS_Store\n" + \
|
78
|
+
"._*\n" + \
|
75
79
|
".recoverdefaults\n"
|
76
80
|
|
77
81
|
STATE_CLOSED = 0
|
@@ -300,11 +304,13 @@ module LEnc
|
|
300
304
|
# @raise IllegalStateException if repository isn't open.
|
301
305
|
#
|
302
306
|
def perform_encrypt()
|
307
|
+
db = warndb 0
|
303
308
|
raise IllegalStateException if @state != STATE_OPEN
|
304
309
|
|
305
310
|
enc_dir = @encrDir
|
306
311
|
if in_place?
|
307
312
|
enc_dir = @repoBaseDir
|
313
|
+
!db || pr("perform_encrypt, enc_dir set to repoBaseDir #{@repoBaseDir}\n")
|
308
314
|
end
|
309
315
|
|
310
316
|
setInputOutputDirs(@startDir,enc_dir)
|
@@ -317,7 +323,7 @@ module LEnc
|
|
317
323
|
puts("Encrypting...") if @verbosity >= 1
|
318
324
|
|
319
325
|
begin
|
320
|
-
|
326
|
+
encrypt_directory_contents(@repoBaseDir, enc_dir)
|
321
327
|
puts("...done.") if @verbosity >= 1
|
322
328
|
end
|
323
329
|
end
|
@@ -763,8 +769,10 @@ module LEnc
|
|
763
769
|
end
|
764
770
|
|
765
771
|
temp_enc_path = convertFile(sourceFile, true, showProgress)
|
772
|
+
!db || pr(" converted [#{sourceFile}] to temp [#{temp_enc_path}]\n")
|
766
773
|
if not @dryrun
|
767
774
|
FileUtils.mv(temp_enc_path, encryptFile)
|
775
|
+
!db || pr(" moved temp to encryptFile #{encryptFile}\n")
|
768
776
|
end
|
769
777
|
|
770
778
|
end
|
@@ -822,9 +830,9 @@ module LEnc
|
|
822
830
|
# @param sourceDir absolute path of source directory
|
823
831
|
# @param encryptDir absolute path of encryption directory
|
824
832
|
#
|
825
|
-
def
|
833
|
+
def encrypt_directory_contents(sourceDir, encryptDir)
|
826
834
|
|
827
|
-
db =
|
835
|
+
db = warndb 0
|
828
836
|
|
829
837
|
!db || pr("\n\nencryptDir\n %s =>\n %s\n",d(sourceDir),d(encryptDir))
|
830
838
|
|
@@ -869,6 +877,7 @@ module LEnc
|
|
869
877
|
# Examine each file in source dir
|
870
878
|
dirc = dir_entries(sourceDir)
|
871
879
|
|
880
|
+
!db || pr(" dirc=%s\n",d2(dirc))
|
872
881
|
dirc.each do |f2|
|
873
882
|
# Convert string to ASCII-8BIT encoding.
|
874
883
|
f = to_ascii8(f2)
|
@@ -909,7 +918,7 @@ module LEnc
|
|
909
918
|
encrPath = File.join(encryptDir, encrName)
|
910
919
|
|
911
920
|
if File.directory?(filePath)
|
912
|
-
|
921
|
+
encrypt_directory_contents(filePath, encrPath)
|
913
922
|
else
|
914
923
|
!db || pr("...attempting to encrypt file #{filePath} to #{encrPath}...\n")
|
915
924
|
encrypt_file(filePath, encrPath)
|
@@ -924,16 +933,17 @@ module LEnc
|
|
924
933
|
end
|
925
934
|
|
926
935
|
if File.directory?(filePath)
|
927
|
-
|
936
|
+
encrypt_directory_contents(filePath, filePath)
|
928
937
|
# Rename the directory to its encrypted form, if necessary
|
929
|
-
if filePath != encrPath
|
938
|
+
if (not @dryrun) && (filePath != encrPath)
|
930
939
|
!db || pr(" renaming now-encrypted file from\n #{filePath}\n to\n #{encrPath}\n")
|
931
940
|
FileUtils.mv(filePath,encrPath)
|
932
941
|
end
|
933
942
|
else
|
934
943
|
encrypt_file(filePath, encrPath)
|
935
944
|
# Delete unencrypted file, if not using original names
|
936
|
-
if
|
945
|
+
if (not @dryrun) && (not @orignames)
|
946
|
+
!db || pr(" attempting to remove unencrypted file #{filePath}\n")
|
937
947
|
FileUtils.rm(filePath)
|
938
948
|
end
|
939
949
|
end
|
@@ -968,7 +978,7 @@ module LEnc
|
|
968
978
|
printf("Removing encrypted version of missing (or ignored) file " \
|
969
979
|
+ rel_path(File.join(sourceDir, orphanOrigName), @inputDir) + ": " + orphanPath)
|
970
980
|
end
|
971
|
-
if
|
981
|
+
if not @dryrun
|
972
982
|
remove_file_or_dir(orphanPath)
|
973
983
|
end
|
974
984
|
rescue DecryptionError
|
@@ -1035,9 +1045,11 @@ module LEnc
|
|
1035
1045
|
if !@orignames
|
1036
1046
|
raise ArgumentError,"decrypted already exists: #{decrPath}" \
|
1037
1047
|
if File.exist?(decrPath)
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1048
|
+
|
1049
|
+
if not @dryrun
|
1050
|
+
!db || pr(" renaming now-decrypted directory from\n #{filePath}\n to\n #{decrPath}\n")
|
1051
|
+
FileUtils.mv(filePath,decrPath)
|
1052
|
+
end
|
1041
1053
|
end
|
1042
1054
|
else
|
1043
1055
|
decrPathDisp = File.join(decr_dir_name,decrName)
|
@@ -1084,7 +1096,9 @@ module LEnc
|
|
1084
1096
|
if File.file?(recoverDir)
|
1085
1097
|
raise RecoveryError, "Cannot replace existing file '" + recoverDir + "' with directory"
|
1086
1098
|
end
|
1087
|
-
|
1099
|
+
if not @dryrun
|
1100
|
+
Dir.mkdir(recoverDir)
|
1101
|
+
end
|
1088
1102
|
end
|
1089
1103
|
|
1090
1104
|
if not File.directory?(encryptDir)
|
@@ -1196,7 +1210,7 @@ module LEnc
|
|
1196
1210
|
|
1197
1211
|
fr = File.open(srcPath, 'rb')
|
1198
1212
|
fw = Tempfile.new("repo")
|
1199
|
-
|
1213
|
+
!db || pr("created temporary file #{fw.path}\n")
|
1200
1214
|
cSize = 100000
|
1201
1215
|
|
1202
1216
|
# Predict number of chunks required
|
@@ -1256,6 +1270,7 @@ module LEnc
|
|
1256
1270
|
pr("\n")
|
1257
1271
|
end
|
1258
1272
|
|
1273
|
+
!db || pr(" (done convertFile)\n")
|
1259
1274
|
fw
|
1260
1275
|
end
|
1261
1276
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lenc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Sember
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-05-
|
11
|
+
date: 2013-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: highline
|
@@ -39,7 +39,6 @@ extensions: []
|
|
39
39
|
extra_rdoc_files: []
|
40
40
|
files:
|
41
41
|
- lib/lenc.rb
|
42
|
-
- lib/lenc/_OLD_tools.rb
|
43
42
|
- lib/lenc/aes.rb
|
44
43
|
- lib/lenc/config_file.rb
|
45
44
|
- lib/lenc/encr.rb
|
data/lib/lenc/_OLD_tools.rb
DELETED
@@ -1,628 +0,0 @@
|
|
1
|
-
require 'set'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
# Various utility and debug convenience functions.
|
5
|
-
#
|
6
|
-
|
7
|
-
# Convenience method to perform 'require_relative' on a set of files
|
8
|
-
#
|
9
|
-
# @param fileListStr space-delimited file/path items, without .rb extensions
|
10
|
-
# @param subdir optional path to files relative to this file
|
11
|
-
#
|
12
|
-
def req(fileListStr,subdir = nil)
|
13
|
-
fileListStr.split(' ').each do |x|
|
14
|
-
if subdir
|
15
|
-
x = File.join(subdir,x)
|
16
|
-
end
|
17
|
-
x += '.rb'
|
18
|
-
require_relative(x)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
# Shorthand for printf(...)
|
23
|
-
# @param args passed to printf
|
24
|
-
def pr(*args)
|
25
|
-
printf(*args)
|
26
|
-
end
|
27
|
-
|
28
|
-
# Convert an object to a human-readable string,
|
29
|
-
# or <nil>; should be considered a debug-only feature
|
30
|
-
#
|
31
|
-
def d(arg)
|
32
|
-
arg.nil? ? "<nil>" : arg.inspect
|
33
|
-
end
|
34
|
-
|
35
|
-
# Convert an object to a human-readable string,
|
36
|
-
# by calling a type-appropriate function: da, dh, or just d.
|
37
|
-
# @param arg object
|
38
|
-
# @param indent optional indentation for pretty printing; if result
|
39
|
-
# spans multiple lines, each line should be indented by this amount
|
40
|
-
#
|
41
|
-
def d2(arg, indent = 0)
|
42
|
-
return da(arg, indent) if arg.is_a? Array
|
43
|
-
return dh(arg, indent) if arg.is_a? Hash
|
44
|
-
return df(arg) if arg.class == FalseClass || arg.class == TrueClass
|
45
|
-
return d(arg)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Convert an object to a human-readable string, prefixed with its type
|
49
|
-
#
|
50
|
-
def dt(arg)
|
51
|
-
if arg.nil?
|
52
|
-
return "<nil>"
|
53
|
-
end
|
54
|
-
s = arg.class.to_s
|
55
|
-
s << ':'
|
56
|
-
s << arg.inspect
|
57
|
-
s
|
58
|
-
end
|
59
|
-
|
60
|
-
# Append a particular number of spaces to a string
|
61
|
-
def add_sp(s, indent = 0)
|
62
|
-
s << ' ' * indent
|
63
|
-
end
|
64
|
-
|
65
|
-
# Pretty-print an array,
|
66
|
-
# one element to a line
|
67
|
-
# @param indent indentation of each line, in spaces
|
68
|
-
def da(array, indent = 0)
|
69
|
-
return d(array) if !array
|
70
|
-
s = 'Array ['
|
71
|
-
indent += 2
|
72
|
-
array.each do |x|
|
73
|
-
s << "\n"
|
74
|
-
add_sp(s,indent)
|
75
|
-
s2 = d2(x, indent + 2)
|
76
|
-
s << s2
|
77
|
-
end
|
78
|
-
s << " ]"
|
79
|
-
s
|
80
|
-
end
|
81
|
-
|
82
|
-
# Pretty-print a hash,
|
83
|
-
# one element to a line
|
84
|
-
# @param indent indentation of each line, in spaces
|
85
|
-
def dh(hash, indent = 0)
|
86
|
-
return d(hash) if !hash
|
87
|
-
s = 'Hash {'
|
88
|
-
indent += 2
|
89
|
-
hash.each_pair do |key,val|
|
90
|
-
s2 = d(key)
|
91
|
-
s3 = d2(val, indent + 4)
|
92
|
-
s << "\n "
|
93
|
-
add_sp(s,indent)
|
94
|
-
s << s2.chomp << " => " << s3.chomp
|
95
|
-
end
|
96
|
-
s << " }"
|
97
|
-
s
|
98
|
-
end
|
99
|
-
|
100
|
-
# Generate debug description of a boolean value
|
101
|
-
# @param flag value to interpret as a boolean; prints 'T' iff not nil
|
102
|
-
# @param label optional label
|
103
|
-
def df(flag, label=nil)
|
104
|
-
s = ''
|
105
|
-
if label
|
106
|
-
s << label << ':'
|
107
|
-
end
|
108
|
-
s << (flag ? "T" : "F")
|
109
|
-
s << ' '
|
110
|
-
s
|
111
|
-
end
|
112
|
-
|
113
|
-
# Assert that a value is true. Should be considered a
|
114
|
-
# very temporary, debug-only option; it is slow and
|
115
|
-
# generates a warning that it is being called.
|
116
|
-
# @param cond condition
|
117
|
-
# @param msg generates additional message using printf(), if these arguments exist
|
118
|
-
def assert!(cond, *msg)
|
119
|
-
one_time_alert("warning",0,"Checking assertion")
|
120
|
-
if not cond
|
121
|
-
str = (msg.size == 0) ? "assertion error" : sprintf(*msg)
|
122
|
-
raise Exception, str
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Extensions to the Enumerable module
|
127
|
-
#
|
128
|
-
module Enumerable
|
129
|
-
# Calculate a value for each item, and return the item with the
|
130
|
-
# highest value, its index, and the value.
|
131
|
-
# @yieldparam function to calculate value of an object, given that object as a parameter
|
132
|
-
# @return the triple [object, index, value] reflecting the maximum value, or
|
133
|
-
# nil if there were no items
|
134
|
-
def max_with_index
|
135
|
-
|
136
|
-
best = nil
|
137
|
-
|
138
|
-
each_with_index do |obj,ind|
|
139
|
-
sc = yield(obj)
|
140
|
-
if !best || best[2] < sc
|
141
|
-
best = [obj,ind,sc]
|
142
|
-
end
|
143
|
-
end
|
144
|
-
best
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# Get a nice, concise description of the file and line
|
149
|
-
# of some caller within the stack.
|
150
|
-
#
|
151
|
-
# @param nSkip the number of items deep in the call stack to look
|
152
|
-
#
|
153
|
-
def get_caller_location(nSkip = 2)
|
154
|
-
|
155
|
-
filename = nil
|
156
|
-
linenumber = nil
|
157
|
-
|
158
|
-
if nSkip >= 0 && nSkip < caller.size
|
159
|
-
fi = caller[nSkip]
|
160
|
-
|
161
|
-
i = fi.index(':')
|
162
|
-
j = nil
|
163
|
-
if i
|
164
|
-
j = fi.index(':',i+1)
|
165
|
-
end
|
166
|
-
if j
|
167
|
-
pth = fi[0,i].split('/')
|
168
|
-
if pth.size
|
169
|
-
filename = pth[-1]
|
170
|
-
end
|
171
|
-
linenumber = fi[i+1,j-i-1]
|
172
|
-
end
|
173
|
-
end
|
174
|
-
if filename && linenumber
|
175
|
-
loc = filename + " ("+linenumber+")"
|
176
|
-
else
|
177
|
-
loc = "(UNKNOWN LOCATION)"
|
178
|
-
end
|
179
|
-
loc
|
180
|
-
end
|
181
|
-
|
182
|
-
# Set of alert strings that have already been reported
|
183
|
-
# (to avoid printing anything on subsequent invocations)
|
184
|
-
#
|
185
|
-
$AlertStrings = Set.new
|
186
|
-
|
187
|
-
# Print a message if it hasn't yet been printed,
|
188
|
-
# which includes the caller's location
|
189
|
-
#
|
190
|
-
# @param typeString e.g., "warning", "unimplemented"
|
191
|
-
# @param nSkip the number of levels deep that the caller is in the stack
|
192
|
-
# @param args if present, calls sprintf(...) with these to append to the message
|
193
|
-
#
|
194
|
-
def one_time_alert(typeString, nSkip, *args)
|
195
|
-
loc = get_caller_location(nSkip + 2)
|
196
|
-
s = "*** "+typeString+" " + loc
|
197
|
-
if args && args.size
|
198
|
-
s2 = sprintf(args[0], *args[1..-1])
|
199
|
-
msg = s + ": " + s2
|
200
|
-
else
|
201
|
-
msg = s
|
202
|
-
end
|
203
|
-
|
204
|
-
if $AlertStrings.add?(msg)
|
205
|
-
puts msg
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
# Print a 'warning' alert, one time only
|
210
|
-
# @param args if present, calls printf() with these
|
211
|
-
def warn(*args)
|
212
|
-
one_time_alert("warning",0, *args)
|
213
|
-
end
|
214
|
-
|
215
|
-
# Convenience method for setting 'db' true within methods,
|
216
|
-
# and to print a one-time warning if so.
|
217
|
-
# @param val value to set db to; it is convenient to disable
|
218
|
-
# debug printing quickly by adding a zero, e.g., 'warndb 0'
|
219
|
-
#
|
220
|
-
def warndb(val = true)
|
221
|
-
if !val || val == 0
|
222
|
-
return false
|
223
|
-
end
|
224
|
-
one_time_alert("warning",1, "Debug printing enabled")
|
225
|
-
true
|
226
|
-
end
|
227
|
-
|
228
|
-
# Print an 'unimplemented' alert, one time only
|
229
|
-
# @param args if present, calls printf() with these
|
230
|
-
def unimp(*args)
|
231
|
-
one_time_alert("unimplemented", 0, *args)
|
232
|
-
end
|
233
|
-
|
234
|
-
# Write a string to a text file
|
235
|
-
#
|
236
|
-
def write_text_file(path, contents)
|
237
|
-
File.open(path, "wb") {|f| f.write(contents) }
|
238
|
-
end
|
239
|
-
|
240
|
-
# Read a file's contents, return as a string
|
241
|
-
#
|
242
|
-
def read_text_file(path)
|
243
|
-
contents = nil
|
244
|
-
File.open(path,"rb") {|f| contents = f.read }
|
245
|
-
contents
|
246
|
-
end
|
247
|
-
|
248
|
-
# Method that takes a code block as an argument to
|
249
|
-
# achieve the same functionality as Java/C++'s
|
250
|
-
# do {
|
251
|
-
# ...
|
252
|
-
# ... possibly with 'break' to jump to the end ...
|
253
|
-
# } while (false);
|
254
|
-
#
|
255
|
-
def block
|
256
|
-
yield
|
257
|
-
end
|
258
|
-
|
259
|
-
# Exception class for objects in illegal states
|
260
|
-
#
|
261
|
-
class IllegalStateException < Exception
|
262
|
-
end
|
263
|
-
|
264
|
-
def to_hex(value, num_digits=4)
|
265
|
-
s = sprintf("%x", value)
|
266
|
-
s.rjust(num_digits,'0')
|
267
|
-
end
|
268
|
-
|
269
|
-
def hex_dump(byte_array_or_string, title=nil, offset=0, length= -1, bytes_per_row=16, with_text=true)
|
270
|
-
ss = hex_dump_to_string(byte_array_or_string, title, offset, length, bytes_per_row, with_text)
|
271
|
-
puts ss
|
272
|
-
end
|
273
|
-
|
274
|
-
def hex_dump_to_string(byte_array_or_string, title=nil, offset=0, length= -1, bytes_per_row=16, with_text=true)
|
275
|
-
|
276
|
-
byte_array = byte_array_or_string
|
277
|
-
if byte_array.is_a? String
|
278
|
-
byte_array = byte_array.bytes.to_a
|
279
|
-
end
|
280
|
-
|
281
|
-
ss = ''
|
282
|
-
|
283
|
-
if title
|
284
|
-
ss << title << ":\n"
|
285
|
-
end
|
286
|
-
|
287
|
-
if length < 0
|
288
|
-
length = byte_array.size - offset
|
289
|
-
end
|
290
|
-
|
291
|
-
length = [length, byte_array.size - offset].min
|
292
|
-
|
293
|
-
max_addr = offset + length - 1
|
294
|
-
num_digits = 4
|
295
|
-
while (1 << (4 * num_digits)) <= max_addr
|
296
|
-
num_digits += 1
|
297
|
-
end
|
298
|
-
|
299
|
-
while true
|
300
|
-
ss << to_hex(offset, num_digits)
|
301
|
-
ss << ': '
|
302
|
-
|
303
|
-
chunk = [length, bytes_per_row].min
|
304
|
-
bytes_per_row.times do |i|
|
305
|
-
if i % 4 == 0
|
306
|
-
ss << ' '
|
307
|
-
end
|
308
|
-
|
309
|
-
if i < chunk
|
310
|
-
v = byte_array[offset + i]
|
311
|
-
ss << ((v != 0) ? to_hex(v,2) : '..')
|
312
|
-
ss << ' '
|
313
|
-
else
|
314
|
-
ss << ' '
|
315
|
-
end
|
316
|
-
|
317
|
-
end
|
318
|
-
|
319
|
-
|
320
|
-
if with_text
|
321
|
-
ss << ' |'
|
322
|
-
bytes_per_row.times do |i|
|
323
|
-
if i < chunk
|
324
|
-
v = byte_array[offset + i]
|
325
|
-
ss << ((v >= 32 && v < 127) ? v : '_')
|
326
|
-
end
|
327
|
-
end
|
328
|
-
ss << '|'
|
329
|
-
end
|
330
|
-
ss << "\n"
|
331
|
-
|
332
|
-
length -= chunk
|
333
|
-
offset += chunk
|
334
|
-
break if length <= 0
|
335
|
-
end
|
336
|
-
|
337
|
-
ss << "\n"
|
338
|
-
ss
|
339
|
-
end
|
340
|
-
|
341
|
-
$prevTime = nil
|
342
|
-
|
343
|
-
# Calculate time elapsed, in seconds, from last call to this function;
|
344
|
-
# if it's never been called, returns zero
|
345
|
-
def elapsed
|
346
|
-
curr = Time.now.to_f
|
347
|
-
elap = 0
|
348
|
-
if $prevTime
|
349
|
-
elap = curr - $prevTime
|
350
|
-
end
|
351
|
-
$prevTime = curr
|
352
|
-
elap
|
353
|
-
end
|
354
|
-
|
355
|
-
# Delete a file or directory, if it exists.
|
356
|
-
# Caution! If directory, deletes all files and subdirectories.
|
357
|
-
def remove_file_or_dir(pth)
|
358
|
-
if File.directory?(pth)
|
359
|
-
FileUtils.remove_dir(pth)
|
360
|
-
elsif File.file?(pth)
|
361
|
-
FileUtils.remove_file(pth)
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
|
-
require 'stringio'
|
366
|
-
|
367
|
-
$IODest = nil
|
368
|
-
$OldStdOut = nil
|
369
|
-
|
370
|
-
def capture_begin
|
371
|
-
raise IllegalStateException if $IODest
|
372
|
-
$IODest = StringIO.new
|
373
|
-
$OldStdOut, $stdout = $stdout, $IODest
|
374
|
-
end
|
375
|
-
|
376
|
-
def capture_end
|
377
|
-
raise IllegalStateException if !$IODest
|
378
|
-
$stdout = $OldStdOut
|
379
|
-
ret = $IODest.string
|
380
|
-
$IODest = nil
|
381
|
-
ret
|
382
|
-
end
|
383
|
-
|
384
|
-
def match_expected_output(str = nil)
|
385
|
-
|
386
|
-
if !str
|
387
|
-
str = capture_end
|
388
|
-
end
|
389
|
-
|
390
|
-
cl_method = caller[0][/`.*'/][1..-2]
|
391
|
-
if (cl_method.start_with?("test_"))
|
392
|
-
cl_method = cl_method[5..-1]
|
393
|
-
end
|
394
|
-
path = "_output_" + cl_method + ".txt"
|
395
|
-
# path = File.absolute_path(path)
|
396
|
-
|
397
|
-
if !File.file?(path)
|
398
|
-
printf("no such file #{path} exists, writing it...\n")
|
399
|
-
writeTextFile(path,str)
|
400
|
-
else
|
401
|
-
exp_cont = read_text_file(path)
|
402
|
-
if str != exp_cont
|
403
|
-
d1 = str
|
404
|
-
d2 = exp_cont
|
405
|
-
# d1 = hex_dump_to_string(str,"Output")
|
406
|
-
# d2 = hex_dump_to_string(exp_cont,"Expected")
|
407
|
-
|
408
|
-
raise IllegalStateException,"output did not match expected:\n#{d1}#{d2}"
|
409
|
-
end
|
410
|
-
end
|
411
|
-
end
|
412
|
-
|
413
|
-
# Convenience method to detect if a script is being run
|
414
|
-
# e.g. as a 'main' method (for debug purposes only).
|
415
|
-
# If so, it changes the current directory to the
|
416
|
-
# directory containing the script (if such a directory exists).
|
417
|
-
#
|
418
|
-
# @param file pass __FILE__ in here
|
419
|
-
# @return true if so
|
420
|
-
#
|
421
|
-
def main?(file)
|
422
|
-
|
423
|
-
scr = $0
|
424
|
-
|
425
|
-
# The test/unit framework seems to be adding a suffix ": xxx#xxx.."
|
426
|
-
# to the .rb filename, so adjust in this case
|
427
|
-
i = scr.index(".rb: ")
|
428
|
-
if i
|
429
|
-
scr = scr[0...i+3]
|
430
|
-
end
|
431
|
-
|
432
|
-
if (ret = (file == scr))
|
433
|
-
dr = File.dirname(file)
|
434
|
-
if File.directory?(dr)
|
435
|
-
Dir.chdir(dr)
|
436
|
-
end
|
437
|
-
end
|
438
|
-
ret
|
439
|
-
end
|
440
|
-
|
441
|
-
if defined? Test::Unit
|
442
|
-
|
443
|
-
# A simple extension to Ruby's Test::Unit class that provides
|
444
|
-
# suite-level setup/teardown methods.
|
445
|
-
#
|
446
|
-
# If test suite functionality is desired within a script,
|
447
|
-
# then require 'test/unit' before requiring 'tools.rb'.
|
448
|
-
# This will cause the following class, MyTestSuite, to be defined.
|
449
|
-
#
|
450
|
-
# The user's test script can define subclasses of this,
|
451
|
-
# and declare test methods with the name 'test_xxxx', where
|
452
|
-
# xxxx is lexicographically between 01 and zz.
|
453
|
-
#
|
454
|
-
# There are two levels of setup/teardown called : suite level, and
|
455
|
-
# method level. For example, if the user's test class performs two tests:
|
456
|
-
#
|
457
|
-
# def test_b ... end
|
458
|
-
# def test_c ... end
|
459
|
-
#
|
460
|
-
# Then the test framework will make these calls:
|
461
|
-
#
|
462
|
-
# suite_setup
|
463
|
-
#
|
464
|
-
# method_setup
|
465
|
-
# test_b
|
466
|
-
# method_teardown
|
467
|
-
#
|
468
|
-
# method_setup
|
469
|
-
# test_c
|
470
|
-
# method_teardown
|
471
|
-
#
|
472
|
-
# suite_teardown
|
473
|
-
#
|
474
|
-
# Notes
|
475
|
-
# -----
|
476
|
-
# 1) The usual setup / teardown methods should NOT be overridden; instead,
|
477
|
-
# use the method_xxx alternatives.
|
478
|
-
#
|
479
|
-
# 2) The base class implementations of method_/suite_xxx do nothing.
|
480
|
-
#
|
481
|
-
# 3) The number of test cases reported may be higher than you expect, since
|
482
|
-
# there are additional test methods defined by the TestSuite class to
|
483
|
-
# implement the suite setup / teardown functionality.
|
484
|
-
#
|
485
|
-
# 4) Avoid naming test methods that fall outside of test_01 ... test_zz.
|
486
|
-
#
|
487
|
-
class MyTestSuite < Test::Unit::TestCase
|
488
|
-
|
489
|
-
# This is named to be the FIRST test called. It
|
490
|
-
# will do suite-level setup, and nothing else.
|
491
|
-
def test_00_setup
|
492
|
-
@@suiteSetup = true
|
493
|
-
suite_setup()
|
494
|
-
end
|
495
|
-
|
496
|
-
# This is named to be the LAST test called. It
|
497
|
-
# will do suite-level teardown, and nothing else.
|
498
|
-
def test_zzzzzz_teardown
|
499
|
-
suite_teardown()
|
500
|
-
@@suiteSetup = false
|
501
|
-
end
|
502
|
-
|
503
|
-
# True if called within suite-level setup/teardown window
|
504
|
-
def _suite_active?
|
505
|
-
!(@__name__ == "test_00_setup" || @__name__ == "test_zzzzzz_teardown")
|
506
|
-
end
|
507
|
-
|
508
|
-
def setup
|
509
|
-
if _suite_active?
|
510
|
-
# If only a specific test was requested, the
|
511
|
-
# suite setup may not have run... if not, do it now.
|
512
|
-
if !defined? @@suiteSetup
|
513
|
-
suite_setup
|
514
|
-
end
|
515
|
-
return
|
516
|
-
end
|
517
|
-
method_setup
|
518
|
-
end
|
519
|
-
|
520
|
-
def teardown
|
521
|
-
if _suite_active?
|
522
|
-
if !defined? @@suiteSetup
|
523
|
-
suite_teardown
|
524
|
-
end
|
525
|
-
return
|
526
|
-
end
|
527
|
-
method_teardown
|
528
|
-
end
|
529
|
-
|
530
|
-
def suite_setup
|
531
|
-
end
|
532
|
-
|
533
|
-
def suite_teardown
|
534
|
-
end
|
535
|
-
|
536
|
-
def method_setup
|
537
|
-
end
|
538
|
-
|
539
|
-
def method_teardown
|
540
|
-
end
|
541
|
-
end
|
542
|
-
end
|
543
|
-
|
544
|
-
# Construct a string from an array of bytes
|
545
|
-
# @param byte_array array of bytes, or string (in which case it
|
546
|
-
# returns it unchanged)
|
547
|
-
#
|
548
|
-
def bytes_to_str(byte_array)
|
549
|
-
return byte_array if byte_array.is_a? String
|
550
|
-
|
551
|
-
byte_array.pack('C*')
|
552
|
-
end
|
553
|
-
|
554
|
-
# Construct an array of bytes from a string
|
555
|
-
# @param str string, or array of bytes (in which case it
|
556
|
-
# returns it unchanged)
|
557
|
-
#
|
558
|
-
def str_to_bytes(str)
|
559
|
-
return str if str.is_a? Array
|
560
|
-
str.bytes
|
561
|
-
end
|
562
|
-
|
563
|
-
# Get directory entries, excluding '.' and '..'
|
564
|
-
#
|
565
|
-
def dir_entries(path)
|
566
|
-
ents = Dir.entries(path)
|
567
|
-
ents.reject!{|entry| entry == '.' || entry == '..'}
|
568
|
-
end
|
569
|
-
|
570
|
-
def int_to_bytes(x)
|
571
|
-
[(x >> 24) & 0xff, (x >> 16) & 0xff, (x >> 8) & 0xff, x & 0xff]
|
572
|
-
end
|
573
|
-
|
574
|
-
def short_to_bytes(x)
|
575
|
-
[(x >> 8) & 0xff, x & 0xff]
|
576
|
-
end
|
577
|
-
|
578
|
-
# Decode a short from an array of bytes (big-endian).
|
579
|
-
# @param ba array of bytes
|
580
|
-
# @param offset offset of first (most significant) byte
|
581
|
-
#
|
582
|
-
def short_from_bytes(ba, offset=0)
|
583
|
-
(ba[offset] << 8) | ba[offset + 1]
|
584
|
-
end
|
585
|
-
|
586
|
-
# Decode an int from an array of bytes (big-endian).
|
587
|
-
# @param ba array of bytes
|
588
|
-
# @param offset offset of first (most significant) byte
|
589
|
-
#
|
590
|
-
def int_from_bytes(ba, offset=0)
|
591
|
-
(((((ba[offset] << 8) | ba[offset + 1]) << 8) | \
|
592
|
-
ba[offset + 2]) << 8) | ba[offset + 3]
|
593
|
-
end
|
594
|
-
|
595
|
-
# Transform string to 8-bit ASCII (i.e., just treat each byte as-is)
|
596
|
-
#
|
597
|
-
def to_ascii8(str)
|
598
|
-
str.force_encoding("ASCII-8BIT")
|
599
|
-
end
|
600
|
-
|
601
|
-
# Verify that a string is encoded as ASCII-8BIT
|
602
|
-
def simple_str(s)
|
603
|
-
if s.encoding.name != 'ASCII-8BIT' && s.encoding.name != 'UTF-8'
|
604
|
-
pr("string [%s]\n encoding is %s,\n expected ASCII-8BIT\n",s,s.encoding.name)
|
605
|
-
assert!(false)
|
606
|
-
end
|
607
|
-
end
|
608
|
-
|
609
|
-
# Truncate or pad string so it has a particular size
|
610
|
-
#
|
611
|
-
# @param s input string
|
612
|
-
# @param size
|
613
|
-
# @param pad padding character to use if string needs to grow
|
614
|
-
# @return modified string
|
615
|
-
#
|
616
|
-
def str_sized(s, size, pad="\0")
|
617
|
-
s[0...size].ljust(size,pad)
|
618
|
-
end
|
619
|
-
|
620
|
-
# Determine if running on the Windows operating system.
|
621
|
-
# Note: there is some debate about the best way to do this.
|
622
|
-
#
|
623
|
-
def windows?
|
624
|
-
if !defined? $__windows__
|
625
|
-
$__windows__ = (RUBY_PLATFORM =~ /mswin/)
|
626
|
-
end
|
627
|
-
$__windows__
|
628
|
-
end
|