bc3 0.1.1 → 0.1.2

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.
@@ -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
-