bc3 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -104,12 +104,6 @@ return the result in a yaml-list.
104
104
 
105
105
  =end
106
106
 
107
- =begin
108
- fixme/test:
109
- duplicates
110
- save as snapshot.
111
- =end
112
-
113
107
  $testmode = false
114
108
  #~ $testmode = true
115
109
  if $testmode
@@ -123,12 +117,12 @@ puts "!!Testmode"
123
117
  $:.unshift('../lib')
124
118
  end
125
119
 
120
+ #~ gem 'bc3', '= 0.1.2beta'
126
121
  require 'optparse'
127
122
  require 'bc3'
128
123
  #~ $log.level = Log4r::DEBUG
129
124
  $log.level = Log4r::WARN
130
125
 
131
-
132
126
  #Collector
133
127
  $options = {
134
128
  duplicates: false,
@@ -0,0 +1,37 @@
1
+ =Change History
2
+ ==0.1.0: 2011-01-24 Initial version
3
+ ==0.1.1: 2011-01-30
4
+ * New: BC3::Snapshot.new_filelist
5
+ * New: BC3::Folder#add_with_path
6
+ * New: bin/bc_search.rb
7
+ * Changed BC3::Snapshot.newh -> BC3::Snapshot.new_hash (newh as alias)
8
+ * Changed BC3::Snapshot.newd -> BC3::Snapshot.new_filesystem (newd as alias)
9
+ * BC3::Snapshot.save saves yaml or bcss file
10
+ * bin/bc_merge.rb can handle yaml-files
11
+ ==0.1.2 2011-02-20
12
+ * BC3::SnapshotParse: Support UTF for linux files
13
+ * BC3::Snapshot#utf: Added flag. Allows creation of Linux-UTF-snapshots.
14
+ * BC3::Snapshot: Support UTF for linux files (Snapshot uses UTF-8).
15
+ * BC3::Snapshot.uncompress: Added
16
+
17
+
18
+
19
+ =Known problems/Todos
20
+
21
+ ==Missing code
22
+ * Snapshot.to_yaml: Add UTF-texts, utf-flag
23
+ * Snapshots/Win32 with Unicode Creation error
24
+
25
+ ==Misc
26
+ * No compression of snapshots (uncompression works)
27
+ * test_reconstruct.rb make little timestamp changes (accuracy of Time?)
28
+
29
+ Tests require BC3-folder comparison in background.
30
+ * Missing unittest for bcss-generation
31
+ * Missing unittest for compressed bcss.
32
+ * Missing unittest for uncompressed bcss.
33
+
34
+ ==Not covered
35
+ The following features of beyond compare are not covered by this tool:
36
+
37
+ * Symbolic links
@@ -0,0 +1 @@
1
+ This folder ist the target for the examples.
@@ -0,0 +1 @@
1
+ All examples in this directory are copies from:
@@ -0,0 +1,49 @@
1
+ =begin
2
+ Take the original examples from becond compare
3
+ (http://www.scootersoftware.com/vbulletin/showthread.php?t=7210),
4
+ parse them and reconstruct them again.
5
+
6
+ =end
7
+ $:.unshift('../lib')
8
+
9
+ require 'bc3'
10
+ require 'yaml'
11
+
12
+ def read_and_save(filename, *options )
13
+ puts "Start #{options.inspect} for #{filename}"
14
+ options.each{|opt|
15
+ puts "undefined option #{opt}" unless %w{bcss xxx yaml yaml_stdout uncompressed}.include?(opt.to_s)
16
+ }
17
+
18
+ target = File.join("results", File.basename(filename))
19
+
20
+ snap = BC3::SnapshotParser.new(filename)
21
+
22
+ puts snap.snapshot.to_hash.to_yaml if options.include?(:yaml_stdout)
23
+ snap.snapshot.save(target.sub('.bcss', '.yaml')) if options.include?(:yaml)
24
+
25
+ snap.snapshot.save(target) if options.include?(:bcss)
26
+
27
+ if options.include?(:uncompressed)
28
+ BC3::Snapshot.uncompress(filename, target.sub('.bcss', '_uncompressed.bcss'))
29
+ end
30
+
31
+ #Copy result to enable binary compare
32
+ FileUtils.copy(filename, target.sub('\.bcss', '.xxx') ) if options.include?(:xxx)
33
+
34
+ end
35
+ #ok with minor binary differences (time stamp in milliseconds-steps)
36
+ read_and_save('scootersoftware/UncompressedSample.bcss', :bcss)
37
+
38
+ #~ $log.level=Log4r::DEBUG
39
+ $log.level=Log4r::WARN
40
+ $log.level=Log4r::INFO
41
+ #~ read_and_save('scootersoftware/UnicodeFilenames(Linux).bcss', :bcss)
42
+ #~ read_and_save('scootersoftware/UnicodePath(Linux).bcss', :bcss)
43
+
44
+ =begin
45
+ 2010-02-01: Will not work correct
46
+ =end
47
+ #--
48
+ #~ read_and_save('scootersoftware/UnicodeFilenames(Win32).bcss', :uncompressed, :bcss, :yaml)
49
+ #~ read_and_save('scootersoftware/UnicodePath(Win32).bcss', :bcss)
data/lib/bc3.rb CHANGED
@@ -85,5 +85,15 @@ require 'bc3/time'
85
85
  require 'bc3/parse'
86
86
 
87
87
  module BC3
88
- VERSION = '0.1.1'
89
- end
88
+ VERSION = '0.1.2'
89
+ end
90
+
91
+ __END__
92
+ fixme logger/sublogger
93
+
94
+ Snapshot definiert logger, vererbt an subloggers dir/file
95
+ gem 'log4r', '>= 1.1.9'
96
+ require 'log4r'
97
+ log = Logger.new('log')
98
+ log2 = Logger.new('log::2::b')
99
+
@@ -47,12 +47,13 @@ Must contain KEYS and supports KEYS_OPTIONAL
47
47
  end
48
48
 
49
49
  =begin rdoc
50
- Create a folder from file system.
50
+ Creates a BC3::File-object, based on data from file system.
51
51
 
52
52
  The argument must contain:
53
- * dirname
53
+ * filename
54
+ * flag, if crc schould be added (default: true)
54
55
  =end
55
- def self.new_by_filename( filename )
56
+ def self.new_by_filename( filename, with_crc = true )
56
57
  $log.debug("Build file #{filename} from file system")
57
58
 
58
59
  #fixme: get attributes from file system
@@ -62,14 +63,15 @@ The argument must contain:
62
63
  settings = {
63
64
  filename: filename,
64
65
  filesize: ::File.size(filename),
65
- #~ attributes: ::File.stat(filename),
66
+ attributes: Attrib.fileattrib(filename),
66
67
  #The timestamp must be 'local time' -> ignore local time zone for generation
67
68
  timestamp: ::File.mtime(filename) + Time.now.gmt_offset,
68
69
  }
69
70
 
70
- ::File.open( filename, 'r'){|f|
71
+ #Binary read needed, else the crc may differ from BC3
72
+ ::File.open( filename, 'rb'){|f|
71
73
  settings[:crc] = Helper::crc32(f.read)
72
- } #fixme crc if ...
74
+ } if with_crc
73
75
  return File.new( settings )
74
76
  end
75
77
  #Name of the file
@@ -79,6 +81,8 @@ The argument must contain:
79
81
  attr_reader :crc
80
82
  #Path (location) in snapshots
81
83
  attr_reader :snapshotpath
84
+ #File attributes
85
+ attr_reader :attributes
82
86
 
83
87
  def to_hash()
84
88
  hash = {
@@ -118,8 +122,7 @@ ID_FILE (0x02)
118
122
  else
119
123
  bcss << 2
120
124
  end
121
- bcss << @filename.size
122
- bcss << @filename
125
+ bcss << shortstring2bcss(@filename)
123
126
  bcss << fixnum2int64(@timestamp.time2ad)
124
127
  #DOS Attributes
125
128
  bcss << @attributes #little endian storage
@@ -169,7 +172,7 @@ FILE_EX_LINK_PATH (0x03)
169
172
 
170
173
  =end
171
174
  def bcss_extended_headers()
172
- ehead = ''
175
+ ehead = ''.force_encoding('binary')
173
176
  if @version
174
177
  ehead << 1
175
178
  ehead << @version.size
@@ -187,13 +190,12 @@ FILE_EX_LINK_PATH (0x03)
187
190
  ehead << utfsymlink.size
188
191
  ehead << utfsymlink
189
192
  end
190
- #fixme
191
193
 
192
- bcss = ''
194
+ bcss = ''.force_encoding('binary')
193
195
  bcss << fixnum2int16(ehead.size + 2) #size including this length
194
196
  bcss << ehead
195
197
 
196
- bcss
198
+ bcss
197
199
  end
198
200
  end #File
199
201
  end #BC3
@@ -63,12 +63,12 @@ The argument must contain:
63
63
  * dirname
64
64
  =end
65
65
  def self.new_by_dirname( dirname )
66
- #fixme: Pattern??
67
- #fixme: attrib
68
66
  $log.debug("Build folder #{dirname} from file system")
69
67
  #The timestamp must be 'local time' -> ignore local time zone for generation
70
68
  folder = new( dirname, ::File.mtime(dirname) + Time.now.gmt_offset )
69
+ #fixme: attrib
71
70
  Dir.chdir(dirname){
71
+ #feature idea: Define Pattern as method parameter??
72
72
  Dir['*'].each{|f|
73
73
  if ::File.directory?(f)
74
74
  folder << Folder.new_by_dirname(f)
@@ -90,6 +90,10 @@ The argument must contain:
90
90
  #timestamp
91
91
  attr_reader :timestamp
92
92
  attr_reader :attributes
93
+ #Part of the Extended Header Subtypes, see BC3::SnapshotParser#parse_extended_header_subtypes
94
+ attr_accessor :ex_utf
95
+ #Part of the Extended Header Subtypes, see BC3::SnapshotParser#parse_extended_header_subtypes
96
+ attr_accessor :ex_link_path
93
97
 
94
98
  =begin rdoc
95
99
  Add content to folder.
@@ -175,11 +179,13 @@ Options may be
175
179
  options = [:folders, :files ] if options.empty? #take all, but not recursive
176
180
 
177
181
  extract = {}
178
- @content.each{|key, content|
182
+ #~ @content.each{|key, content|
183
+ #~ @content.sort_by{|key, x| x.is_a?(Folder) ? 'a' : 'b' + x.basename }.each{|key, content|
184
+ @content.sort_by{|key, x| ( x.is_a?(Folder) ? 'a%s/' : 'b%s' ) % x.basename }.each{|key, content|
179
185
  case content
180
186
  when File
181
187
  extract[key] = content if options.include?(:files)
182
- when Folder
188
+ when Folder
183
189
  extract[key+'/'] = content if options.include?(:folders)
184
190
  else
185
191
  raise "Internal error"
@@ -198,8 +204,8 @@ Options may be
198
204
  extract
199
205
  end
200
206
  end
201
-
202
- #~ def values();@content.values;end #fixme
207
+ =begin rdoc
208
+ =end
203
209
  def inspect()
204
210
  "<BC3::Folder #{@dirname}>"
205
211
  end
@@ -207,12 +213,14 @@ Options may be
207
213
  Return the content in a hash.
208
214
  =end
209
215
  def to_hash()
210
- #fixme: Array with needed keys?
216
+ #feature idea: Optional array with needed keys?
211
217
  {
212
218
  dirname: @dirname,
213
219
  timestamp: @timestamp,
214
220
  attributes: @attributes,
215
- content: @content.values.map{|x| x.to_hash }
221
+ #use each to get a sorted output
222
+ #~ content: @content.values.map{|x| x.to_hash }
223
+ content: self.each.values.map{|x| x.to_hash }
216
224
  }
217
225
  end
218
226
  =begin rdoc
@@ -234,8 +242,7 @@ ID_DIRECTORY_END (0xFF)
234
242
  def bcss()
235
243
  bcss = "".force_encoding('BINARY')
236
244
  bcss << 1
237
- bcss << @dirname.size
238
- bcss << @dirname
245
+ bcss << shortstring2bcss(@dirname)
239
246
  bcss << fixnum2int64(@timestamp.time2ad)
240
247
  #DOS Attributes
241
248
  bcss << @attributes
@@ -248,6 +255,25 @@ ID_DIRECTORY_END (0xFF)
248
255
  }
249
256
 
250
257
  bcss << 255
258
+ if ex_utf
259
+ $log.fatal("Untested ex_utf")
260
+ bcss << 'xxxx'
261
+ bcss << 4 #Extended Header Subtypes
262
+ =begin
263
+ EX_UTF8 (0x01)
264
+ UTF-8 encoded filename for the ID_DIRECTORY that immediately preceeded
265
+ this header. The length is given in the ID_EXTENDED header and the data is a
266
+ char[].
267
+ If the .bcss header flags indicate that the data is not UTF-8 and the
268
+ source path is included this can be included as the first record in the file
269
+ in order to give a UTF-8 version of the source path.
270
+ =end
271
+ bcss << 1
272
+ bcss << ex_utf.bytesize
273
+ #~ p ex_utf.bytesize
274
+ #~ p ex_utf
275
+ bcss << shortstring2bcss(ex_utf.dup.force_encoding('binary'))
276
+ end
251
277
  bcss
252
278
  end
253
279
  end #Folder
@@ -21,7 +21,7 @@ http://www.xxcopy.com/xxcopy06.htm
21
21
  0 1 0 0 0 0 0 0 40h Reserved
22
22
  1 0 0 0 0 0 0 0 80h Reserved
23
23
 
24
- Usage:
24
+ Usage
25
25
  attrib = Attrib::ReadOnly | Attrib::Hidden
26
26
  =end
27
27
  module Attrib
@@ -31,6 +31,30 @@ module Attrib
31
31
  VolumeLabel = 8
32
32
  Directory = 16
33
33
  Archive = 32
34
+ =begin
35
+ How to read attributs/windows:
36
+ http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/68298
37
+
38
+ Easier: call attrib and analyse output
39
+
40
+ fixme: CHeck OS
41
+ =end
42
+ def self.fileattrib(filename)
43
+ attrib = 0
44
+
45
+ raise ArgumentError, "Filename #{filename} not found" unless ::File.exists?(filename)
46
+
47
+ attrib += Directory if ::File.directory?(filename)
48
+ res = `attrib #{filename}`
49
+
50
+ attrib += ReadOnly if res =~ /\A\S*R/
51
+ attrib += Hidden if res =~ /\A\S*H/
52
+ attrib += System if res =~ /\A\S*S/
53
+ #~ attrib += VolumeLabel = if res =~ /\A\S*/
54
+ attrib += Archive if res =~ /\A\S*A/
55
+
56
+ attrib
57
+ end
34
58
  end
35
59
 
36
60
  =begin rdoc
@@ -81,6 +105,7 @@ AD's epoch (Bignum) as an bit sequence.
81
105
  ('%064b' % int).scan(/(\d{8})/).flatten.reverse.each{|b|
82
106
  bindata << b.to_i(2)
83
107
  }
108
+ raise ArgumentError unless $~.post_match.empty?
84
109
  raise ArgumentError unless bindata.size == 8 #int was too big
85
110
  bindata
86
111
  end
@@ -93,6 +118,7 @@ Same as Helper#fixnum2int64, but as 4 bytes string.
93
118
  ('%032b' % int).scan(/(\d{8})/).flatten.reverse.each{|b|
94
119
  bindata << b.to_i(2)
95
120
  }
121
+ raise ArgumentError unless $~.post_match.empty?
96
122
  raise ArgumentError unless bindata.size == 4 #int was too big
97
123
  bindata
98
124
  end
@@ -105,9 +131,30 @@ Same as Helper#fixnum2int64, but as 2 bytes string.
105
131
  ('%016b' % int).scan(/(\d{8})/).flatten.reverse.each{|b|
106
132
  bindata << b.to_i(2)
107
133
  }
134
+ raise ArgumentError unless $~.post_match.empty?
108
135
  raise ArgumentError unless bindata.size == 2 #int was too big
109
136
  bindata
110
137
  end
111
138
 
139
+ =begin rdoc
140
+ Save a shortstring to bcss
141
+
142
+ ShortString:
143
+ Variable length single-byte character string (ANSI or UTF-8).
144
+ Not null terminated.
145
+
146
+ UTF-8: If set the snapshot was compressed on a system where the default
147
+ character encoding is UTF-8 (Linux, OS X). Filenames, paths, and link targets
148
+ will all be stored as UTF-8. If this isn't set the paths are stored using the
149
+ original OS's ANSI codepage (Windows). In that case any paths may be stored a
150
+ second time as UTF-8 in extended headers.
151
+
152
+ =end
153
+ def shortstring2bcss(shortstring)
154
+ bcss = "".force_encoding('BINARY')
155
+ bcss << shortstring.bytesize
156
+ bcss << shortstring.dup.force_encoding('binary')
157
+ bcss
158
+ end
112
159
  end #Helper
113
160
  end #BC3
@@ -3,10 +3,9 @@ Parser for BC3-Snapshots.
3
3
 
4
4
  The snapshot may be compressed or uncompressed.
5
5
 
6
- No support for UTF-8.
6
+ Test see examples/test_reconstruct.
7
+
7
8
  =end
8
- $:.unshift('..') if $0 == __FILE__ #only test
9
- require 'bc3'
10
9
 
11
10
  require "zlib"
12
11
  module BC3
@@ -67,19 +66,20 @@ Parser for a given bcss-file.
67
66
  @compressed = rawdata[16].getbyte(0) & 1 != 0
68
67
  @sourcepath = rawdata[16].getbyte(0) & 2 != 0
69
68
  @reserved = rawdata[16].getbyte(0) & 4 != 0
70
- @utf = rawdata[16].getbyte(0) & 8 != 0
69
+ @utf = rawdata[16].getbyte(0) & 8 != 0
70
+ @log.warn("UTF-data") if @utf
71
71
  if rawdata[17] != "\x0"
72
72
  @log.warn("2nd flag byte is filled")
73
73
  end
74
74
 
75
75
  #Analyse Source path
76
-
77
76
  #Delete second length parameter for source path
78
77
  if rawdata.slice!(19) != "\x0"
79
78
  @log.warn("Path > 255 not supported")
80
79
  raise "Path > 255 not supported"
81
80
  end
82
81
  path, body = parse_shortstring(rawdata[18..-1])
82
+ path.force_encoding('utf-8') if @utf
83
83
  if @compressed
84
84
  =begin
85
85
  Flags:
@@ -101,9 +101,10 @@ Code from http://www.ruby-forum.com/topic/136825
101
101
  end
102
102
 
103
103
  @snapshot = Snapshot.new(path, @timestamp)
104
-
104
+ @snapshot.utf = @utf
105
+
105
106
  parse_body(body)
106
- end #initialize
107
+ end #read_bcss
107
108
  #Snapshot-object, result of the parsing.
108
109
  attr_reader :snapshot
109
110
  attr_reader :timestamp
@@ -193,6 +194,16 @@ ID_FILE_EX (0x03)
193
194
  }.merge(extradata)
194
195
  )
195
196
  =begin
197
+ ID_EXTENDED (0x04)
198
+ Extended headers
199
+
200
+ SubType : UByte
201
+ Length : UWord
202
+ Data : Byte[Length]
203
+ =end
204
+ when "\x04" #file
205
+ parse_extended_header_subtypes(body, folderstack.last)
206
+ =begin
196
207
  ID_DIRECTORY_END (0xFF)
197
208
  Represents the end of a directory listing. No data.
198
209
  =end
@@ -205,8 +216,7 @@ ID_DIRECTORY_END (0xFF)
205
216
  end
206
217
  end
207
218
  if folderstack.size > 1
208
- @log.error("Folders in Folderstack not closed correct")
209
- p folderstack.size
219
+ @log.error("Folders in Folderstack not closed correct - #{folderstack.size} levels open")
210
220
  end
211
221
  end
212
222
  =begin rdoc
@@ -216,12 +226,17 @@ Get a "shortstring".
216
226
 
217
227
  Return shortstring and rest of string.
218
228
  =end
219
- def parse_shortstring( string )
229
+ def parse_shortstring( string )
220
230
  #Get length of path
221
231
  pathsize = string.slice!(0).bytes.first
222
232
  # + rawdata[19].bytes.first * 255 #--test it
223
- return [string.slice!(0,pathsize), string]
233
+ if @utf
234
+ return [string.slice!(0,pathsize).force_encoding('utf-8'), string]
235
+ else
236
+ return [string.slice!(0,pathsize), string]
237
+ end
224
238
  end
239
+
225
240
  =begin rdoc
226
241
  Get a "longstring".
227
242
 
@@ -236,6 +251,11 @@ Return longstring and rest of string.
236
251
  @log.warn("longstring > 255 not supported")
237
252
  raise "longstring > 255 not supported"
238
253
  end
254
+ if @utf
255
+ return [string.slice!(0,stringsize).force_encoding('utf-8'), string]
256
+ else
257
+ return [string.slice!(0,stringsize), string]
258
+ end
239
259
  return [string.slice!(0,stringsize), string]
240
260
  end
241
261
  =begin rdoc
@@ -300,7 +320,7 @@ FILE_EX_LINK_PATH (0x03)
300
320
  #loop on extradata...
301
321
  while !extradata_string.empty?
302
322
  case flag = extradata_string.slice!(0)
303
- when "\x01"
323
+ when "\x01" #version
304
324
  extradata[:version], extradata_string = parse_shortstring( extradata_string )
305
325
  when "\x02" #UTF-8 encoded filename
306
326
  extradata[:utfpath], extradata_string = parse_shortstring( extradata_string )
@@ -319,19 +339,76 @@ FILE_EX_LINK_PATH (0x03)
319
339
  #~ end
320
340
  extradata
321
341
  end
342
+ =begin rdoc
343
+ ========================
344
+ Extended Header Subtypes
345
+ ========================
346
+
347
+ Extended headers should be written in ascending numeric order. Once BC sees
348
+ an extended subtype that it doesn't undertand it stops processing ID_EXTENDED
349
+ headers until it finds one of ID_DIRECTORY/ID_DIRECTORY_END/ID_FILE/ID_FILE_EX.
350
+
351
+ Side effect: the parameter will be shortened.
352
+ =end
353
+ def parse_extended_header_subtypes(data, last_folder)
354
+ continue = true
355
+ while continue
356
+ case flag = data.slice!(0)
357
+ =begin
358
+ EX_UTF8 (0x01)
359
+ UTF-8 encoded filename for the ID_DIRECTORY that immediately preceeded
360
+ this header. The length is given in the ID_EXTENDED header and the data is a
361
+ char[].
362
+ If the .bcss header flags indicate that the data is not UTF-8 and the
363
+ source path is included this can be included as the first record in the file
364
+ in order to give a UTF-8 version of the source path.
365
+ =end
366
+ when "\x01"
367
+ ex_utf, data = parse_shortstring( data )
368
+ last_folder.ex_utf = ex_utf.force_encoding('utf-8')
369
+ =begin
370
+ EX_DIRECTORY_EX (0x02)
371
+ Extended directory header for the ID_DIRECTORY that immediately preceeded
372
+ this header. Data is the record below, but Length may be larger to support
373
+ future expansion.
374
+
375
+ Flags : UByte
376
+ Bit : Meaning
377
+ 0 : Error - Contents not available. Flag as a load error in BC.
378
+ =end
379
+ when "\x02" #UTF-8 encoded filename
380
+ @log.fatal("Undefined extended_header_subtypes 2")
381
+ ex_directory_ex = data.slice!(0)
382
+ =begin
383
+ EX_RESYNC (0x03)
384
+ Works around a bug in Beyond Compare's parser in versions prior to 3.2.2.
385
+ If an ID_DIRECTORY is followed by any ID_EXTENDED headers besides EX_UTF8 or
386
+ EX_DIRECTORY_EX include one copy of this header before them.
387
+
388
+ Length : UWord = 0x0001
389
+ Data : Byte[1] = 0
390
+ =end
391
+ when "\x03" #UTF-8 encoded symbolic link path
392
+ @log.fatal("Undefined extended_header_subtypes 3")
393
+ size = data.slice!(0).bytes.first
394
+ ex_resync = data.slice!(size)
395
+ =begin
396
+ EX_LINK_PATH (0x04)
397
+ UTF-8 encoded symbolic link path for the ID_DIRECTORY that immediately
398
+ preceeded this header. The length is given in the ID_EXTENDED header and the
399
+ data is a char[].
400
+ =end
401
+ when "\x04" #UTF-8 encoded symbolic link path
402
+ @log.fatal("Undefined extended_header_subtypes 4")
403
+ ex_link_path, data = parse_shortstring( data )
404
+ last_folder.ex_link_path = ex_link_path.force_encoding('utf-8')
405
+ else
406
+ @log.debug("Stop extended header subtype handling #{flag.inspect} <#{data.inspect}>")
407
+ continue = false #stop evaluation
408
+ end
409
+ end #while continue
410
+ end #parse_extended_header_subtypes
411
+
322
412
  end #SnapshotParser
323
413
  def to_hash; @snapshot.to_hash; end
324
414
  end
325
-
326
- if $0 == __FILE__
327
- require 'yaml'
328
- #~ x = BC3::SnapshotParser.new('../../examples/results/testdir_2011-01-16.bcssx' )
329
- #~ x = BC3::SnapshotParser.new('../../examples/results/bc3_2011-01-16.bcss' )
330
- x = BC3::SnapshotParser.new('../../Uncompressed Sample/Uncompressed Sample.bcss' )
331
- #~ puts x.snapshot.to_hash.to_yaml
332
- x.snapshot.save('../../Uncompressed Sample/Uncompressed Sample_reconstructed.bcss')
333
- FileUtils.copy(
334
- '../../Uncompressed Sample/Uncompressed Sample_reconstructed.bcss',
335
- '../../Uncompressed Sample/Uncompressed Sample_reconstructed.xxxx'
336
- )
337
- end
@@ -49,6 +49,8 @@ A snapsot-hash must contain:
49
49
  raise ArgumentError, "Content is no array" unless data[:content].is_a?(Array)
50
50
 
51
51
  snapshot = new( data[:snapshot], data[:timestamp] )
52
+ snapshot.utf = data[:utf]
53
+
52
54
  data[:content].each{| element |
53
55
  if element.has_key?(:dirname)
54
56
  snapshot << Folder.newh(element)
@@ -114,18 +116,67 @@ Empty folders end with a slash.
114
116
  snap
115
117
  end #self.new_filelist
116
118
 
117
- #Keep old definition
119
+ #Keep old definition, version 0.1.0
118
120
  class << self
119
121
  alias :newd :new_filesystem
120
122
  alias :newh :new_hash
121
123
  end
122
124
 
125
+ =begin rdoc
126
+ Uncompress a snapshot and save it again.
127
+ =end
128
+ def self.uncompress(filename, filename2 = nil)
129
+ rawdata = nil
130
+ ::File.open( filename, 'rb' ){|f| rawdata = f.read() }
131
+
132
+ compressed = rawdata[16].getbyte(0) & 1 != 0
133
+
134
+ pathlength = rawdata.slice(18).bytes.first
135
+ if rawdata.slice(19) != "\x0"
136
+ @log.warn("Path > 255 not supported")
137
+ raise "Path > 255 not supported"
138
+ end
139
+ path = rawdata[20,pathlength]
140
+
141
+ header = rawdata[0,16]
142
+ if compressed
143
+ header << (rawdata.slice(16).bytes.first - 1)
144
+ else
145
+ header << rawdata.slice(16)
146
+ end
147
+ header << rawdata[17,3] #keep original length
148
+ #~ header << path.bytesize #byte 18
149
+ #~ header << 0 #byte 19 - for long pathes
150
+ header << path
151
+
152
+ #will change again for compressed data
153
+ body = rawdata[20 + pathlength ..-1]
154
+ if compressed
155
+ begin
156
+ body= Zlib::Inflate.inflate(body); #Unclear problem
157
+ rescue Zlib::DataError
158
+ $log.debug("Zlib::DataError occured - try with raw deflate")
159
+ #no luck with Zlib decompression. Let's try with raw deflate,
160
+ #like some broken browsers do.
161
+ body= Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(body)
162
+ end
163
+ end
164
+
165
+ ::File.open( filename2, 'wb' ){|f|
166
+ f << header
167
+ f << body
168
+ } if filename2
169
+ header+body
170
+ end
171
+
123
172
  #homepath of the snapshot
124
173
  attr_reader :path
125
174
  #Content of the snapshot
126
175
  attr_reader :basefolder
127
176
  #Time stamp from snapshot. Default 'now'
128
177
  attr_reader :timestamp
178
+ #UTF-Flag. Is set by SnapshotParser#read_bcss
179
+ attr_accessor :utf
129
180
 
130
181
  =begin rdoc
131
182
  Add content (folders/files) to snapshot.
@@ -265,11 +316,14 @@ Usefull in combination with yaml:
265
316
  puts snapshot.to_hash.to_yaml
266
317
  =end
267
318
  def to_hash()
268
- {
269
- snapshot: @path,
270
- timestamp: @timestamp,
271
- content: @basefolder.each.values.map{| x | x.to_hash }
272
- }
319
+ result = {
320
+ snapshot: @path,
321
+ timestamp: @timestamp,
322
+ content: @basefolder.each.values.map{| x | x.to_hash }
323
+ }
324
+ result[:utf] = @utf unless @utf.nil?
325
+
326
+ result
273
327
  end
274
328
  =begin rdoc
275
329
  Prepare a snapshot (bcss-file).
@@ -380,24 +434,25 @@ second time as UTF-8 in extended headers.
380
434
 
381
435
  # [10..11] = Flags (UWord)
382
436
 
383
- #~ Bit : Meaning
384
- #~ 0 : Compressed
385
- #~ 1 : Source Path included
386
- #~ 2 : Reserved
387
- #~ 3 : UTF-8
437
+ #~ Bit/Value : Meaning
438
+ #~ 0/1 : Compressed
439
+ #~ 1/2 : Source Path included
440
+ #~ 2/4 : Reserved
441
+ #~ 3/8 : UTF-8
388
442
  #~ 4-15 : Reserved
389
443
  flag = 0 #no flag set
390
444
  flag += 2 #Source Path included
391
445
  flag += 1 if compressed
446
+ flag += 8 if @utf
392
447
  header << flag
393
448
  header << 0
394
449
 
395
450
  # [12..13] = Path Length (UWord) | Optional
396
- header << @path.size
451
+ header << @path.bytesize
397
452
  header << 0 #fixme if path > 255
398
453
  raise "too long path" if @path.size > 155 #fixme
399
454
  # [14..N] = Path (char[]) |
400
- header << @path
455
+ header << @path.dup.force_encoding('binary')
401
456
 
402
457
  header
403
458
  end #header
@@ -1 +1 @@
1
- =begin rdoc
2
1
  bignum too big to convert into `unsigned long' (RangeError)
3
2
  AD_EPOCH = 116_444_736_000_000_000
4
3
  AD_MULTIPLIER = 10_000_000
5
4
  # convert a Time object to AD's epoch
6
5
  def time2ad()
7
6
  (self.to_i * AD_MULTIPLIER) + AD_EPOCH
8
7
  end
9
8
  # convert from AD's time string to a Time object
10
9
  def self.ad2time(time)
11
10
  Time.at((time.to_i - AD_EPOCH) / AD_MULTIPLIER)
12
11
  end
12
+ =begin rdoc
13
13
  bignum too big to convert into `unsigned long' (RangeError)
14
14
  AD_EPOCH = 116_444_736_000_000_000
15
15
  AD_MULTIPLIER = 10_000_000
16
16
  # convert a Time object to AD's epoch
17
17
  def time2ad()
18
18
  (self.to_f * AD_MULTIPLIER) + AD_EPOCH
19
19
  end
20
20
  # convert from AD's time string to a Time object
21
21
  def self.ad2time(time)
22
22
  Time.at((time.to_f - AD_EPOCH) / AD_MULTIPLIER)
23
23
  end
@@ -30,6 +30,19 @@ class Test_file < Test::Unit::TestCase
30
30
  assert_equal('x', file.basename )
31
31
  assert_equal(file.filename, file.basename )
32
32
  end
33
+ def test_new_by_filename()
34
+ file = BC3::File.new_by_filename( __FILE__)
35
+ assert_equal(__FILE__, file.filename )
36
+ assert_equal(__FILE__, file.basename )
37
+ assert_equal(file.filename, file.basename )
38
+ assert_kind_of(Integer, file.crc )
39
+ ##Sure?
40
+ assert_equal(BC3::Attrib::Archive, file.attributes )
41
+
42
+ #Test without crc
43
+ file = BC3::File.new_by_filename( __FILE__, false)
44
+ assert_equal(nil, file.crc )
45
+ end
33
46
  def test_hash()
34
47
  assert_equal( { filename: 'f', filesize: 5, timestamp: $timestamp, attributes: BC3::Attrib::Archive, crc: nil},
35
48
  BC3::File.new( filename: 'f', filesize: 5, timestamp: $timestamp ).to_hash
@@ -192,14 +192,14 @@ class Test_folder < Test::Unit::TestCase
192
192
  assert_equal( %w{dir2/test.txt},folder.each(:recursive,:files).keys )
193
193
 
194
194
  folder.add_with_path('dir2/subdir', BC3::File.new(filename: 'test.txt', filesize: 5 ))
195
- assert_equal( %w{dir2/test.txt dir2/subdir/test.txt},folder.each(:recursive,:files).keys )
195
+ assert_equal( %w{dir2/subdir/test.txt dir2/test.txt},folder.each(:recursive,:files).keys )
196
196
 
197
197
  folder.add_with_path('dir4/subdir', BC3::File.new(filename: 'test.txt', filesize: 5 ))
198
- assert_equal( %w{dir2/test.txt dir2/subdir/test.txt dir4/subdir/test.txt},folder.each(:recursive,:files).keys )
198
+ assert_equal( %w{dir2/subdir/test.txt dir2/test.txt dir4/subdir/test.txt},folder.each(:recursive,:files).keys )
199
199
 
200
- #Added at end - sorting not necessary.
200
+ #Added at end, but each is sorted.
201
201
  folder.add_with_path('dir0', BC3::File.new(filename: 'test.txt', filesize: 5 ))
202
- assert_equal( %w{dir2/test.txt dir2/subdir/test.txt dir4/subdir/test.txt dir0/test.txt},folder.each(:recursive,:files).keys )
202
+ assert_equal( %w{dir0/test.txt dir2/subdir/test.txt dir2/test.txt dir4/subdir/test.txt},folder.each(:recursive,:files).keys )
203
203
  end
204
204
  end
205
205
 
@@ -0,0 +1,44 @@
1
+ gem 'test-unit'
2
+ require 'test/unit'
3
+
4
+ $:.unshift('../lib')
5
+ require 'bc3/helper'
6
+
7
+ class Test_helper < Test::Unit::TestCase
8
+ include BC3::Helper
9
+ def test_fixnum2int64()
10
+ assert_equal("\x05\x00\x00\x00\x00\x00\x00\x00", fixnum2int64(5))
11
+ assert_equal("\xff\x00\x00\x00\x00\x00\x00\x00", fixnum2int64(255))
12
+ assert_equal("\x00\x01\x00\x00\x00\x00\x00\x00", fixnum2int64(256))
13
+ assert_equal("\x01\x01\x00\x00\x00\x00\x00\x00", fixnum2int64(257))
14
+ assert_equal("\x00\x04\x00\x00\x00\x00\x00\x00", fixnum2int64(1024))
15
+ assert_equal("\xff\xff\xff\xff\xff\xff\xff\xff", fixnum2int64( 'ffffffffffffffff'.to_i(16)))
16
+
17
+ assert_raise(ArgumentError){fixnum2int64('ffffffffffffffff'.to_i(16) + 1)}
18
+ end
19
+ def test_fixnum2int32()
20
+ assert_equal("\x05\x00\x00\x00", fixnum2int32(5))
21
+ assert_equal("\xff\x00\x00\x00", fixnum2int32(255))
22
+ assert_equal("\x00\x01\x00\x00", fixnum2int32(256))
23
+ assert_equal("\x01\x01\x00\x00", fixnum2int32(257))
24
+ assert_equal("\x00\x04\x00\x00", fixnum2int32(1024))
25
+ assert_equal("\xff\xff\xff\xff", fixnum2int32( 'ffffffff'.to_i(16)))
26
+
27
+ assert_raise(ArgumentError){fixnum2int32('ffffffff'.to_i(16) + 1)}
28
+ end
29
+ def test_fixnum2int16()
30
+ assert_equal("\x05\x00", fixnum2int16(5))
31
+ assert_equal("\xff\x00", fixnum2int16(255))
32
+ assert_equal("\x00\x01", fixnum2int16(256))
33
+ assert_equal("\x01\x01", fixnum2int16(257))
34
+ assert_equal("\x00\x04", fixnum2int16(1024))
35
+ assert_equal("\xff\xff", fixnum2int16( 'ffff'.to_i(16)))
36
+
37
+ assert_raise(ArgumentError){fixnum2int16('ffff'.to_i(16) + 1)}
38
+ end
39
+ def test_crc32()
40
+ assert_equal('CBF43926', '%X' % BC3::Helper.crc32('123456789'))
41
+ assert_equal('D87F7E0C', '%X' % BC3::Helper.crc32('test'))
42
+ end
43
+ end
44
+
@@ -81,6 +81,7 @@ class Test_merge < Test::Unit::TestCase
81
81
  merge = {
82
82
  snapshot: 'merge_b',
83
83
  timestamp: result[:timestamp],
84
+ utf: false,
84
85
  content: [
85
86
  { dirname: 'snap1', timestamp: $timestamp, attributes: 16, content: Snap1[:content] },
86
87
  { dirname: 'snap2', timestamp: $timestamp, attributes: 16, content: Snap2[:content] },
@@ -98,6 +99,7 @@ class Test_merge < Test::Unit::TestCase
98
99
  merge = {
99
100
  snapshot: 'merge_i',
100
101
  timestamp: result[:timestamp],
102
+ utf: false,
101
103
  content: Snap1[:content] + Snap2[:content]
102
104
  }
103
105
  assert_equal(merge, result)
@@ -64,8 +64,9 @@ class Test_snapshot < Test::Unit::TestCase
64
64
 
65
65
  hash[:content] << { filename: 'file2', filesize: 15, timestamp: $timestamp, crc: nil, attributes: BC3::Attrib::Archive, }
66
66
  assert_equal(hash, BC3::Snapshot.new_hash( hash ).to_hash)
67
-
68
- hash[:content] << { dirname: 'dir1', timestamp: $timestamp, :content => [], attributes: BC3::Attrib::Directory, }
67
+
68
+ #No <<, sort must be seen
69
+ hash[:content].unshift({ dirname: 'dir1', timestamp: $timestamp, :content => [], attributes: BC3::Attrib::Directory, })
69
70
  assert_equal(hash, BC3::Snapshot.new_hash( hash ).to_hash)
70
71
  end
71
72
  def test_new_filesystem()
@@ -104,17 +105,17 @@ class Test_snapshot < Test::Unit::TestCase
104
105
  )
105
106
 
106
107
  assert_equal( %w{
107
- file
108
108
  folder/
109
- folder/file1
110
109
  folder/subfolder/
111
110
  folder/subfolder/subfile1
112
111
  folder/subfolder2/
112
+ folder/file1
113
+ file
113
114
  }, bc3.each(:files, :folders ).keys)
114
115
 
115
116
  assert_equal( %w{
116
- file
117
117
  folder/
118
+ file
118
119
  }, bc3.each(:rootonly, :files, :folders ).keys)
119
120
 
120
121
  assert_equal( %w{
@@ -124,9 +125,9 @@ class Test_snapshot < Test::Unit::TestCase
124
125
  }, bc3.each(:folders ).keys)
125
126
 
126
127
  assert_equal( %w{
127
- file
128
- folder/file1
129
128
  folder/subfolder/subfile1
129
+ folder/file1
130
+ file
130
131
  }, bc3.each(:files ).keys)
131
132
 
132
133
 
@@ -220,12 +221,12 @@ class Test_snapshot < Test::Unit::TestCase
220
221
 
221
222
  #test index
222
223
  assert_equal(%w{
223
- file
224
224
  folder/
225
- folder/file1
226
225
  folder/subfolder/
227
226
  folder/subfolder/subfile1
228
227
  folder/subfolder2/
228
+ folder/file1
229
+ file
229
230
  }, bc3.index.keys)
230
231
  end #test_index
231
232
  def test_index_automatic_reset()
@@ -0,0 +1,95 @@
1
+ =begin rdoc
2
+ There is a problem with nanoseconds.
3
+ -> test_conversion_nanoseconds and test_conversion_now are inactivated.
4
+ =end
5
+ gem 'test-unit'
6
+ require 'test/unit'
7
+
8
+ $:.unshift('../lib')
9
+ require 'bc3/time'
10
+
11
+ class Test_time < Test::Unit::TestCase
12
+ #Nonoseconds are ignored (missing feature in Time-class?)
13
+ def test_ad2time()
14
+ assert_equal('2006-08-17 09:19:04 000000000',
15
+ Time.ad2time(128002727440000000).strftime("%Y-%m-%d %H:%M:%S %9N")
16
+ )
17
+ assert_equal('2006-08-17 09:18:20 000000000',
18
+ Time.ad2time(128002727000000000).strftime("%Y-%m-%d %H:%M:%S %9N")
19
+ )
20
+
21
+ assert_match(/2006-08-17 09:19:04 08082\d\d\d\d/,
22
+ Time.ad2time(128002727440808261).strftime("%Y-%m-%d %H:%M:%S %9N")
23
+ )
24
+ #~ assert_equal('2006-08-17 09:19:04 0808261',
25
+ assert_equal('2006-08-17 09:19:04 080825567', #??
26
+ Time.ad2time(128002727440808261).strftime("%Y-%m-%d %H:%M:%S %9N")
27
+ )
28
+ end
29
+
30
+ def test_time2ad()
31
+ assert_equal(128002464000000000, Time.utc(2006,8,17).time2ad())
32
+ assert_equal(128002727440000000, Time.local(2006,8,17,9,19,4).time2ad())
33
+
34
+ #Test does not work. Split in two areas (high/Low) makes calculating unpossible.
35
+ #~ p 60 * 60 * 1_000_000_000 #one hour in nanoseconds
36
+ #~ assert_equal( 3_600_000_000_000, #one hour in nanoseconds
37
+ #~ Time.utc(2006,8,17,12).time2ad() - Time.utc(2006,8,17,11).time2ad()
38
+ #~ )
39
+
40
+ #~ assert_equal( 3_600_000_000_000, #one hour in nanoseconds
41
+ #~ Time.utc(2006,8,17).time2ad() - Time.local(2006,8,17).time2ad()
42
+ #~ )
43
+ end
44
+ def test_conversions()
45
+ testtime = Time.utc(2006,8,17)
46
+ assert_equal(testtime, Time.ad2time(testtime.time2ad))
47
+
48
+ testtime = Time.local(2006,8,17)
49
+ assert_equal(testtime, Time.ad2time(testtime.time2ad))
50
+ end
51
+
52
+
53
+ def test_conversion_ok()
54
+
55
+ #last 7 digits must be 0.
56
+ last_logon = 129393178970000000
57
+
58
+ time = Time.ad2time(last_logon)
59
+ last_logon2 = time.time2ad()
60
+ time2 = Time.ad2time(last_logon2)
61
+
62
+ assert_equal(time, time2)
63
+
64
+ assert_equal(0, last_logon - last_logon2)
65
+ assert_equal(last_logon, last_logon2)
66
+ end
67
+ def test_conversion_nanoseconds()
68
+
69
+ #last 7 digits are nano seconds.
70
+ last_logon = 129393178978310001
71
+ time = Time.ad2time(last_logon)
72
+
73
+ last_logon2 = time.time2ad()
74
+ time2 = Time.ad2time(last_logon2)
75
+
76
+ #~ assert_in_delta(0, time - time2, 0.001)
77
+ assert_equal(0, time - time2)
78
+ assert_equal(time, time2)
79
+
80
+ assert_equal(0, last_logon - last_logon2)
81
+ assert_equal(last_logon, last_logon2)
82
+
83
+ end
84
+ #
85
+ def test_conversion_now()
86
+ testtime = Time.now
87
+ #problem:
88
+ #AD-time is "the number of 100-nanosecond intervals since ..."
89
+ #Time.now is nanoseconds
90
+ assert_in_delta(0, testtime - Time.ad2time(testtime.time2ad), 1E-6)
91
+ #~ assert_equal(0, testtime - Time.ad2time(testtime.time2ad))
92
+ #~ assert_equal(testtime, Time.ad2time(testtime.time2ad))
93
+ end
94
+ end
95
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bc3
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Knut Lickert
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-30 00:00:00 +01:00
18
+ date: 2011-02-20 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -47,9 +47,11 @@ extensions: []
47
47
 
48
48
  extra_rdoc_files:
49
49
  - BCSS_Binary_Format.txt
50
+ - changes.rd
50
51
  - bin/bc3_merge.rb
51
52
  - bin/bc3_search.rb
52
53
  files:
54
+ - changes.rd
53
55
  - BCSS_Binary_Format.txt
54
56
  - bin/bc3_merge.rb
55
57
  - bin/bc3_search.rb
@@ -60,19 +62,28 @@ files:
60
62
  - lib/bc3/parse.rb
61
63
  - lib/bc3/snapshot.rb
62
64
  - lib/bc3/time.rb
63
- - unittest/unittest_bc3.rb
64
- - unittest/unittest_bc3_file.rb
65
- - unittest/unittest_bc3_folder.rb
66
- - unittest/unittest_bc3_snapshot.rb
67
- - unittest/unittest_bc3_merge.rb
68
- - unittest/unittest_bc3_search.rb
69
65
  - examples/test_combine.rb
70
66
  - examples/test_filesystem.rb
71
67
  - examples/test_hardcoded.rb
72
68
  - examples/test_yaml.rb
69
+ - examples/test_reconstruct.rb
73
70
  - examples/test_merge.bat
74
71
  - examples/folder1_2011-01-21.bcss
75
72
  - examples/folder2_2011-01-21.bcss
73
+ - examples/results/readme
74
+ - examples/scootersoftware/readme
75
+ - examples/scootersoftware/UncompressedSample.bcss
76
+ - examples/scootersoftware/UnicodeFilenames(Linux).bcss
77
+ - examples/scootersoftware/UnicodePath(Linux).bcss
78
+ - examples/scootersoftware/UnicodeFilenames(Win32).bcss
79
+ - examples/scootersoftware/UnicodePath(Win32).bcss
80
+ - unittest/unittest_bc3_helper.rb
81
+ - unittest/unittest_bc3_time.rb
82
+ - unittest/unittest_bc3_file.rb
83
+ - unittest/unittest_bc3_folder.rb
84
+ - unittest/unittest_bc3_snapshot.rb
85
+ - unittest/unittest_bc3_merge.rb
86
+ - unittest/unittest_bc3_search.rb
76
87
  has_rdoc: true
77
88
  homepage: http://gems.rubypla.net/bc3
78
89
  licenses: []
@@ -109,16 +120,10 @@ signing_key:
109
120
  specification_version: 3
110
121
  summary: Build and analyse Beyond Compare (BC3) Snapshot-Files.
111
122
  test_files:
112
- - unittest/unittest_bc3.rb
123
+ - unittest/unittest_bc3_helper.rb
124
+ - unittest/unittest_bc3_time.rb
113
125
  - unittest/unittest_bc3_file.rb
114
126
  - unittest/unittest_bc3_folder.rb
115
127
  - unittest/unittest_bc3_snapshot.rb
116
128
  - unittest/unittest_bc3_merge.rb
117
129
  - unittest/unittest_bc3_search.rb
118
- - examples/test_combine.rb
119
- - examples/test_filesystem.rb
120
- - examples/test_hardcoded.rb
121
- - examples/test_yaml.rb
122
- - examples/test_merge.bat
123
- - examples/folder1_2011-01-21.bcss
124
- - examples/folder2_2011-01-21.bcss
@@ -1,66 +0,0 @@
1
- gem 'test-unit'
2
- require 'test/unit'
3
-
4
- $:.unshift('../lib')
5
- require 'bc3'
6
-
7
- class Test_helper < Test::Unit::TestCase
8
- include BC3::Helper
9
- def test_fixnum2int64()
10
- assert_equal("\x05\x00\x00\x00\x00\x00\x00\x00", fixnum2int64(5))
11
- assert_equal("\xff\x00\x00\x00\x00\x00\x00\x00", fixnum2int64(255))
12
- assert_equal("\x00\x01\x00\x00\x00\x00\x00\x00", fixnum2int64(256))
13
- assert_equal("\x01\x01\x00\x00\x00\x00\x00\x00", fixnum2int64(257))
14
- assert_equal("\x00\x04\x00\x00\x00\x00\x00\x00", fixnum2int64(1024))
15
- end
16
- def test_fixnum2int32()
17
- assert_equal("\x05\x00\x00\x00", fixnum2int32(5))
18
- assert_equal("\xff\x00\x00\x00", fixnum2int32(255))
19
- assert_equal("\x00\x01\x00\x00", fixnum2int32(256))
20
- assert_equal("\x01\x01\x00\x00", fixnum2int32(257))
21
- assert_equal("\x00\x04\x00\x00", fixnum2int32(1024))
22
- end
23
- def test_crc32()
24
- assert_equal('CBF43926', '%X' % BC3::Helper.crc32('123456789'))
25
- assert_equal('D87F7E0C', '%X' % BC3::Helper.crc32('test'))
26
- end
27
- end
28
-
29
-
30
- class Test_time < Test::Unit::TestCase
31
- #Nonoseconds are ignored (missing feature in Time-class?)
32
- def test_ad2time()
33
- assert_equal('2006-08-17 09:19:04 000000000',
34
- Time.ad2time(128002727440808261).strftime("%Y-%m-%d %H:%M:%S %9N")
35
- )
36
- assert_equal('2006-08-17 09:19:04 000000000',
37
- Time.ad2time(128002727440000000).strftime("%Y-%m-%d %H:%M:%S %9N")
38
- )
39
- end
40
- def test_time2ad()
41
- assert_equal(128002464000000000, Time.utc(2006,8,17).time2ad())
42
- assert_equal(128002727440000000, Time.local(2006,8,17,9,19,4).time2ad())
43
-
44
- #Test does not work. Split in two areas (high/Low) makes calculating unpossible.
45
- #~ p 60 * 60 * 1_000_000_000 #one hour in nanoseconds
46
- #~ assert_equal( 3_600_000_000_000, #one hour in nanoseconds
47
- #~ Time.utc(2006,8,17,12).time2ad() - Time.utc(2006,8,17,11).time2ad()
48
- #~ )
49
-
50
- #~ assert_equal( 3_600_000_000_000, #one hour in nanoseconds
51
- #~ Time.utc(2006,8,17).time2ad() - Time.local(2006,8,17).time2ad()
52
- #~ )
53
- end
54
- def test_conversions()
55
- testtime = Time.utc(2006,8,17)
56
- assert_equal(testtime, Time.ad2time(testtime.time2ad))
57
-
58
- testtime = Time.local(2006,8,17)
59
- assert_equal(testtime, Time.ad2time(testtime.time2ad))
60
-
61
- #Test with now does not work. Changed nanoseconds?
62
- #~ testtime = Time.now
63
- #~ assert_equal(testtime, Time.ad2time(testtime.time2ad))
64
- end
65
- end
66
-