trace_visualization 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +6 -0
- data/LICENSE +339 -0
- data/LICENSE.txt +22 -0
- data/README.md +4 -0
- data/Rakefile +1 -0
- data/lib/trace_visualization/bwt.rb +32 -0
- data/lib/trace_visualization/bwt.rbold +32 -0
- data/lib/trace_visualization/data/irepetition.rb +49 -0
- data/lib/trace_visualization/data/repetition.rb +101 -0
- data/lib/trace_visualization/generators.rb +53 -0
- data/lib/trace_visualization/longest_common_prefix.rb +34 -0
- data/lib/trace_visualization/mapping.rb +120 -0
- data/lib/trace_visualization/reorder.rb +25 -0
- data/lib/trace_visualization/repetitions.rb +66 -0
- data/lib/trace_visualization/repetitions_concatenation.rb +134 -0
- data/lib/trace_visualization/repetitions_context.rb +18 -0
- data/lib/trace_visualization/repetitions_incrementation.rb +81 -0
- data/lib/trace_visualization/repetitions_psy.rb +83 -0
- data/lib/trace_visualization/suffix_array.rb +203 -0
- data/lib/trace_visualization/utils.rb +47 -0
- data/lib/trace_visualization/version.rb +3 -0
- data/lib/trace_visualization/visualization/console_color_print.rb +32 -0
- data/lib/trace_visualization.rb +10 -0
- data/spec/bwt_spec.rb +47 -0
- data/spec/generators_spec.rb +30 -0
- data/spec/longest_common_prefix_spec.rb +29 -0
- data/spec/mapping_spec.rb +67 -0
- data/spec/reorder_spec.rb +42 -0
- data/spec/repetitions_concatenation_spec.rb +58 -0
- data/spec/repetitions_incrementation_spec.rb +88 -0
- data/spec/repetitions_psy_spec.rb +39 -0
- data/spec/repetitions_spec.rb +18 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/suffix_array_spec.rb +68 -0
- data/trace_visualization.gemspec +35 -0
- metadata +204 -0
@@ -0,0 +1,203 @@
|
|
1
|
+
module TraceVisualization
|
2
|
+
module SuffixArray
|
3
|
+
def self.naive(str)
|
4
|
+
n = str.length
|
5
|
+
|
6
|
+
tmp = Array.new(n)
|
7
|
+
result = Array.new(n)
|
8
|
+
|
9
|
+
for i in 0 ... n
|
10
|
+
tmp[i] = [str[i .. -1], i]
|
11
|
+
end
|
12
|
+
|
13
|
+
tmp.sort! { |x, y| x[0] <=> y[0] }
|
14
|
+
|
15
|
+
for i in 0 ... n
|
16
|
+
result[i] = tmp[i][1]
|
17
|
+
end
|
18
|
+
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.effective(str)
|
23
|
+
n = str.length
|
24
|
+
s = []
|
25
|
+
|
26
|
+
if str.instance_of? String
|
27
|
+
str.each_char { |c| s << c.ord }
|
28
|
+
elsif str.instance_of? Array
|
29
|
+
str.each { |c| s << c.ord }
|
30
|
+
end
|
31
|
+
|
32
|
+
3.times { s << 0 }
|
33
|
+
|
34
|
+
suffix_array = Array.new(n + 3, 0)
|
35
|
+
|
36
|
+
effective_linear(s, suffix_array, n, s.max + 1)
|
37
|
+
|
38
|
+
suffix_array[0 ... -3]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Find the suffix array SA.
|
42
|
+
# Used approach from article "Linear Work Suffix Array Construction"
|
43
|
+
# by Juha Karkkainen, Peter Sanders and Stefan Burkhardt
|
44
|
+
def self.effective_linear(s, suffix_array, n, alphabet_size)
|
45
|
+
n0 = (n + 2) / 3
|
46
|
+
n1 = (n + 1) / 3
|
47
|
+
n2 = n / 3
|
48
|
+
n02 = n0 + n2
|
49
|
+
|
50
|
+
s12 = Array.new(n02 + 3, 0)
|
51
|
+
sa12 = Array.new(n02 + 3, 0)
|
52
|
+
s0 = Array.new(n0, 0)
|
53
|
+
sa0 = Array.new(n0, 0)
|
54
|
+
|
55
|
+
# Generate positions of mod 1 and mod 2 suffixes
|
56
|
+
# the "+(n0-n1)" adds a dummy mod 1 suffix if n%3 == 1
|
57
|
+
i = j = 0
|
58
|
+
while (i < n + (n0 - n1))
|
59
|
+
if i % 3 != 0
|
60
|
+
s12[j] = i
|
61
|
+
j += 1
|
62
|
+
end
|
63
|
+
i += 1
|
64
|
+
end
|
65
|
+
|
66
|
+
# LSB radix sort the mod 1 and mod 2 triples
|
67
|
+
radix_pass(s12, sa12, s[2 ... s.length], n02, alphabet_size)
|
68
|
+
radix_pass(sa12, s12, s[1 ... s.length], n02, alphabet_size)
|
69
|
+
radix_pass(s12, sa12, s, n02, alphabet_size)
|
70
|
+
|
71
|
+
# Find lexicographic names of triples
|
72
|
+
name, c0, c1, c2 = 0, -1, -1, -1
|
73
|
+
for i in 0 ... n02
|
74
|
+
if (s[sa12[i]] != c0 || s[sa12[i] + 1] != c1 || s[sa12[i] + 2] != c2)
|
75
|
+
name += 1
|
76
|
+
c0 = s[sa12[i]]
|
77
|
+
c1 = s[sa12[i] + 1]
|
78
|
+
c2 = s[sa12[i] + 2]
|
79
|
+
end
|
80
|
+
|
81
|
+
if (sa12[i] % 3 == 1)
|
82
|
+
s12[sa12[i]/3] = name # Left half
|
83
|
+
else
|
84
|
+
s12[sa12[i]/3 + n0] = name # Right half
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Recurse if names are not yet unique
|
89
|
+
if name < n02
|
90
|
+
effective_linear(s12, sa12, n02, name)
|
91
|
+
|
92
|
+
# Store unique names in s12 using the suffix array
|
93
|
+
for i in 0 ... n02
|
94
|
+
s12[sa12[i]] = i + 1
|
95
|
+
end
|
96
|
+
else
|
97
|
+
# Generate the suffix array of s12 directly
|
98
|
+
for i in 0 ... n02
|
99
|
+
sa12[s12[i] - 1] = i
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Stably sort the mod 0 suffixes from sa12 by their first character
|
104
|
+
i, j = 0, 0
|
105
|
+
while i < n02
|
106
|
+
if sa12[i] < n0
|
107
|
+
s0[j] = 3 * sa12[i]
|
108
|
+
j += 1
|
109
|
+
end
|
110
|
+
i += 1
|
111
|
+
end
|
112
|
+
radix_pass(s0, sa0, s, n0, alphabet_size)
|
113
|
+
|
114
|
+
# Merge sorted sa0 suffixes and sorted sa12 suffixes
|
115
|
+
p, t, k = 0, n0 - n1, 0
|
116
|
+
|
117
|
+
while k < n
|
118
|
+
# Pos of current offset 12 suffix
|
119
|
+
i = get_i(n0, sa12, t)
|
120
|
+
|
121
|
+
# Pos of current offset 0 suffix
|
122
|
+
j = sa0[p]
|
123
|
+
|
124
|
+
# Different compares for mod 1 and mod 2 suffixes
|
125
|
+
if (sa12[t] < n0 ? leq_pairs(s[i], s12[sa12[t] + n0], s[j], s12[j/3]) : leq_triples(s[i], s[i + 1], s12[sa12[t] - n0 + 1], s[j], s[j + 1], s12[j/3 + n0]))
|
126
|
+
suffix_array[k] = i
|
127
|
+
t += 1
|
128
|
+
if t == n02
|
129
|
+
# Done: only sa0 suffixes left
|
130
|
+
k += 1
|
131
|
+
while p < n0
|
132
|
+
suffix_array[k] = sa0[p]
|
133
|
+
p += 1
|
134
|
+
k += 1
|
135
|
+
end
|
136
|
+
end
|
137
|
+
else
|
138
|
+
suffix_array[k] = j
|
139
|
+
p += 1;
|
140
|
+
if p == n0
|
141
|
+
# Done: only sa12 suffixes left
|
142
|
+
k += 1
|
143
|
+
while t < n02
|
144
|
+
suffix_array[k] = get_i(n0, sa12, t)
|
145
|
+
t += 1
|
146
|
+
k += 1
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
k += 1
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
private
|
157
|
+
|
158
|
+
# Stably sort a[0 .. n - 1] to b[0 .. n - 1] with keys in 0 .. K from r
|
159
|
+
# Params:
|
160
|
+
# +a+:: positions in r for sort
|
161
|
+
# +b+:: sorted positions in r
|
162
|
+
# +r+:: source
|
163
|
+
# +n+:: number of positions in a and b
|
164
|
+
# +k+:: size of alphabet
|
165
|
+
def self.radix_pass(a, b, r, n, k)
|
166
|
+
c = Array.new(k + 1, 0)
|
167
|
+
|
168
|
+
# Count occurrences
|
169
|
+
for i in 0 ... n
|
170
|
+
c[r[a[i]]] += 1
|
171
|
+
end
|
172
|
+
|
173
|
+
# Exclusive prefix sums
|
174
|
+
sum = 0
|
175
|
+
for i in 0 .. k
|
176
|
+
t = c[i]
|
177
|
+
c[i] = sum
|
178
|
+
sum += t
|
179
|
+
end
|
180
|
+
|
181
|
+
# Sort
|
182
|
+
for i in 0 ... n
|
183
|
+
b[c[r[a[i]]]] = a[i]
|
184
|
+
c[r[a[i]]] += 1
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def self.get_i(n0, sa12, t)
|
189
|
+
sa12[t] < n0 ? sa12[t] * 3 + 1 : (sa12[t] - n0) * 3 + 2
|
190
|
+
end
|
191
|
+
|
192
|
+
# Lexicographic order for pairs
|
193
|
+
def self.leq_pairs(a1, a2, b1, b2)
|
194
|
+
a1 < b1 || a1 == b1 && a2 <= b2
|
195
|
+
end
|
196
|
+
|
197
|
+
# Lexicographic order for triples
|
198
|
+
def self.leq_triples(a1, a2, a3, b1, b2, b3)
|
199
|
+
a1 < b1 || a1 == b1 && leq_pairs(a2, a3, b2, b3)
|
200
|
+
end
|
201
|
+
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module TraceVisualization
|
2
|
+
module Utils
|
3
|
+
|
4
|
+
def self.rhash(lp, rp)
|
5
|
+
lp.hash + rp.hash
|
6
|
+
end
|
7
|
+
|
8
|
+
# Get the start position of lines
|
9
|
+
def self.lines_pos(str)
|
10
|
+
lines_pos = [0]
|
11
|
+
pos = -1
|
12
|
+
|
13
|
+
while (pos = str.index(/\n/, pos + 1))
|
14
|
+
lines_pos << pos + 1 if pos + 1 < str.length
|
15
|
+
end
|
16
|
+
|
17
|
+
lines_pos
|
18
|
+
end
|
19
|
+
|
20
|
+
# Repetitions by line
|
21
|
+
def self.rs_by_line(rs, lines_pos, rs_by_line)
|
22
|
+
for r in rs
|
23
|
+
r_pos = r.left_positions
|
24
|
+
r.lines = []
|
25
|
+
i, j = 0, 0
|
26
|
+
|
27
|
+
while (i < lines_pos.size && j < r_pos.size)
|
28
|
+
a, b = lines_pos[i], (i + 1 < lines_pos.size ? lines_pos[i + 1] : 2**32)
|
29
|
+
|
30
|
+
if a <= r_pos[j] && r_pos[j] < b
|
31
|
+
rs_by_line[i] << [r, r_pos[j]]
|
32
|
+
r.lines << i
|
33
|
+
|
34
|
+
j += 1
|
35
|
+
else
|
36
|
+
i += 1
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
rs_by_line.each { |item| item.sort! { |a, b| a[1] <=> b[1] } }
|
42
|
+
|
43
|
+
rs_by_line
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module Utils
|
47
|
+
end # module TraceVisualization
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'travis/data/repetition'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
module Visualization
|
5
|
+
module ConsoleColorPrint
|
6
|
+
|
7
|
+
GRN = "\033[1;32m"
|
8
|
+
YLW = "\033[1;33m"
|
9
|
+
FNSH = "\033[0m"
|
10
|
+
|
11
|
+
def self.hl(str, repetition)
|
12
|
+
result = ""
|
13
|
+
prev_position = 0
|
14
|
+
positions = repetition.build_positions
|
15
|
+
|
16
|
+
positions.each do |position|
|
17
|
+
result += str[prev_position ... position[0][0]]
|
18
|
+
|
19
|
+
for i in 0 ... position.size
|
20
|
+
pos, len = position[i]
|
21
|
+
result += GRN + "#{str[pos ... pos + len]}" + FNSH
|
22
|
+
result += YLW + "#{str[pos + len ... position[i + 1][0]]}" + FNSH if i < position.size - 1
|
23
|
+
end
|
24
|
+
|
25
|
+
prev_position = position[-1][0] + position[-1][1]
|
26
|
+
end
|
27
|
+
|
28
|
+
result += str[prev_position .. -1]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/spec/bwt_spec.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'trace_visualization'
|
2
|
+
require 'trace_visualization/bwt'
|
3
|
+
require 'trace_visualization/mapping'
|
4
|
+
require 'trace_visualization/suffix_array'
|
5
|
+
|
6
|
+
describe TraceVisualization::BurrowsWheelerTransform do
|
7
|
+
it "naive approach" do
|
8
|
+
str = "^BANANA|"
|
9
|
+
|
10
|
+
bwt = TraceVisualization::BurrowsWheelerTransform.naive(str)
|
11
|
+
|
12
|
+
bwt.should eq ["B", "N", "N", "^", "A", "A", "|", "A"]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "effective implementation" do
|
16
|
+
str = "abaababa"
|
17
|
+
|
18
|
+
bwt = TraceVisualization::BurrowsWheelerTransform.bwt(str, TraceVisualization::SuffixArray.effective(str), str.length)
|
19
|
+
bwt.should eq ["b", "b", "b", "a", "a", "a", "a", "a"]
|
20
|
+
|
21
|
+
|
22
|
+
10.times do
|
23
|
+
rnd_str = (0 ... 60).map { (65 + rand(26)).chr }.join + TraceVisualization::TERMINATION_CHAR
|
24
|
+
|
25
|
+
sa_naive = TraceVisualization::SuffixArray.naive(rnd_str)
|
26
|
+
sa_effective = TraceVisualization::SuffixArray.effective(rnd_str)
|
27
|
+
sa_effective.should eq sa_naive
|
28
|
+
|
29
|
+
bwt_naive = TraceVisualization::BurrowsWheelerTransform.naive(rnd_str)
|
30
|
+
bwt_effective = TraceVisualization::BurrowsWheelerTransform.bwt(rnd_str, TraceVisualization::SuffixArray.effective(rnd_str), rnd_str.length)
|
31
|
+
|
32
|
+
bwt_effective.should eq bwt_naive
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it "test with mapping" do
|
37
|
+
str = "127.0.0.1 a 127.0.0.1 b"
|
38
|
+
arr = TraceVisualization::Mapping.parse(str)
|
39
|
+
ip, ws, a, b = arr[0], arr[1], arr[2], arr[6]
|
40
|
+
|
41
|
+
bwt = TraceVisualization::BurrowsWheelerTransform.bwt(arr, TraceVisualization::SuffixArray.effective(arr), arr.length)
|
42
|
+
bwt_str = TraceVisualization::Mapping.restore(bwt)
|
43
|
+
|
44
|
+
bwt.should eq [ip, ip, a, ws, ws, b, ws]
|
45
|
+
bwt_str.should eq "127.0.0.1127.0.0.1a b "
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'trace_visualization/generators'
|
2
|
+
|
3
|
+
describe TraceVisualization::Generators do
|
4
|
+
describe TraceVisualization::Generators::Thue do
|
5
|
+
it "thue_2_3" do
|
6
|
+
TraceVisualization::Generators::Thue.str_2_3(0).should eq "a"
|
7
|
+
TraceVisualization::Generators::Thue.str_2_3(1).should eq "ab"
|
8
|
+
TraceVisualization::Generators::Thue.str_2_3(2).should eq "abba"
|
9
|
+
TraceVisualization::Generators::Thue.str_2_3(3).should eq "abbabaab"
|
10
|
+
TraceVisualization::Generators::Thue.str_2_3(4).should eq "abbabaabbaababba"
|
11
|
+
TraceVisualization::Generators::Thue.str_2_3(5).should eq "abbabaabbaababbabaababbaabbabaab"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "thue_3_2" do
|
15
|
+
TraceVisualization::Generators::Thue.str_3_2(0).should eq "a"
|
16
|
+
TraceVisualization::Generators::Thue.str_3_2(1).should eq "abcab"
|
17
|
+
TraceVisualization::Generators::Thue.str_3_2(2).should eq "abcabacabcbacbcacbabcabacabcb"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "fibonacci" do
|
21
|
+
TraceVisualization::Generators::Fibonacci.str(0).should eq "b"
|
22
|
+
TraceVisualization::Generators::Fibonacci.str(1).should eq "a"
|
23
|
+
TraceVisualization::Generators::Fibonacci.str(2).should eq "ab"
|
24
|
+
TraceVisualization::Generators::Fibonacci.str(3).should eq "aba"
|
25
|
+
TraceVisualization::Generators::Fibonacci.str(4).should eq "abaab"
|
26
|
+
TraceVisualization::Generators::Fibonacci.str(5).should eq "abaababa"
|
27
|
+
TraceVisualization::Generators::Fibonacci.str(6).should eq "abaababaabaab"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'trace_visualization/longest_common_prefix'
|
2
|
+
require 'trace_visualization/suffix_array'
|
3
|
+
require 'trace_visualization/mapping'
|
4
|
+
|
5
|
+
describe TraceVisualization::LongestCommonPrefix do
|
6
|
+
|
7
|
+
context '.effective' do
|
8
|
+
it 'should return array with longest common prefix in linear time' do
|
9
|
+
str = "mississippi"
|
10
|
+
|
11
|
+
sa = TraceVisualization::SuffixArray.effective(str)
|
12
|
+
lcp = TraceVisualization::LongestCommonPrefix.effective(str, sa, str.size)
|
13
|
+
|
14
|
+
lcp.should eq([0, 1, 1, 4, 0, 0, 1, 0, 2, 1, 3])
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should return correct result for mapped string', :current => true do
|
18
|
+
str = "127.0.0.1 foo\r\n127.0.0.1 bar"
|
19
|
+
arr = TraceVisualization::Mapping.parse(str)
|
20
|
+
|
21
|
+
sa = TraceVisualization::SuffixArray.effective(arr)
|
22
|
+
lcp = TraceVisualization::LongestCommonPrefix.effective(arr, sa, arr.size)
|
23
|
+
|
24
|
+
sa.should eq([6, 5, 8, 1, 10, 9, 2, 4, 3, 11, 7, 0])
|
25
|
+
lcp.should eq([0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 2])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'trace_visualization/mapping'
|
2
|
+
|
3
|
+
describe TraceVisualization::Mapping do
|
4
|
+
it "simple id values" do
|
5
|
+
str = "foo[1234]bar[1235]far[1234]"
|
6
|
+
|
7
|
+
arr = TraceVisualization::Mapping.parse(str)
|
8
|
+
|
9
|
+
arr.size.should eq(12)
|
10
|
+
|
11
|
+
|
12
|
+
ids = arr.find_all { |item| item.type == "id" }
|
13
|
+
ids.size.should eq(3)
|
14
|
+
ids[0].src.should eq("[1234]")
|
15
|
+
ids[1].src.should eq("[1235]")
|
16
|
+
ids[2].src.should eq("[1234]")
|
17
|
+
ids[0].should eq(ids[2])
|
18
|
+
|
19
|
+
str2 = TraceVisualization::Mapping.restore(arr)
|
20
|
+
str2.should eq(str)
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
it "ip values" do
|
25
|
+
str = "user1 ip : 127.0.0.1 \r\nuser2 ip : 127.0.0.2"
|
26
|
+
|
27
|
+
arr = TraceVisualization::Mapping.parse(str)
|
28
|
+
arr.size.should eq(27)
|
29
|
+
|
30
|
+
ips = arr.find_all { |item| item.type == "ip" }
|
31
|
+
ips.size.should eq(2)
|
32
|
+
ips[0].src.should eq("127.0.0.1")
|
33
|
+
ips[1].src.should eq("127.0.0.2")
|
34
|
+
|
35
|
+
str2 = TraceVisualization::Mapping.restore(arr)
|
36
|
+
str2.should eq(str)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "compare different types" do
|
40
|
+
# Ids
|
41
|
+
id_1 = TraceVisualization::Mapping::Item.new("[12345678]", "id")
|
42
|
+
id_2 = TraceVisualization::Mapping::Item.new("[12345679]", "id")
|
43
|
+
TraceVisualization::Reorder.process([id_1, id_2])
|
44
|
+
|
45
|
+
id_1.should be < id_2
|
46
|
+
|
47
|
+
# IPs
|
48
|
+
ip_1 = TraceVisualization::Mapping::Item.new("127.0.0.1", "ip")
|
49
|
+
ip_2 = TraceVisualization::Mapping::Item.new("127.0.0.2", "ip")
|
50
|
+
TraceVisualization::Reorder.process([ip_1, ip_2])
|
51
|
+
|
52
|
+
ip_1.should be < ip_2
|
53
|
+
|
54
|
+
# Time
|
55
|
+
time_1 = TraceVisualization::Mapping::Item.new("[16 Jan 2013 00:10:00]", "time")
|
56
|
+
time_2 = TraceVisualization::Mapping::Item.new("[16 Jan 2013 00:10:01]", "time")
|
57
|
+
TraceVisualization::Reorder.process([time_1, time_2])
|
58
|
+
|
59
|
+
# Different
|
60
|
+
TraceVisualization::Reorder.process([time_1, time_2, id_1, ip_1])
|
61
|
+
|
62
|
+
time_1.should be < time_2
|
63
|
+
id_1.should be < ip_1
|
64
|
+
id_1.should be < time_1
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'trace_visualization/reorder'
|
2
|
+
|
3
|
+
describe TraceVisualization::Reorder do
|
4
|
+
|
5
|
+
class A
|
6
|
+
include Comparable
|
7
|
+
|
8
|
+
attr_accessor :ord
|
9
|
+
attr_accessor :value
|
10
|
+
|
11
|
+
def initialize(theValue)
|
12
|
+
@value = theValue
|
13
|
+
end
|
14
|
+
|
15
|
+
def <=>(anOther)
|
16
|
+
@value <=> anOther.value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "reorder values and set correct order" do
|
21
|
+
data = Array.new(100) { |index| A.new(index * 100) }
|
22
|
+
data.shuffle!
|
23
|
+
|
24
|
+
TraceVisualization::Reorder.process(data)
|
25
|
+
|
26
|
+
data.each { |item| item.ord.should eq(item.value / 100 + 1) }
|
27
|
+
end
|
28
|
+
|
29
|
+
it "duplicate values with the same order", :current => true do
|
30
|
+
x1, x2 = A.new(1), A.new(2)
|
31
|
+
x3, x4 = A.new(123456789), A.new(123456789)
|
32
|
+
|
33
|
+
data = [x1, x2, x3, x4].shuffle
|
34
|
+
|
35
|
+
TraceVisualization::Reorder.process(data)
|
36
|
+
|
37
|
+
x1.ord.should eq(1)
|
38
|
+
x2.ord.should eq(2)
|
39
|
+
x3.ord.should eq(3)
|
40
|
+
x4.ord.should eq(3)
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'trace_visualization/repetitions_concatenation'
|
2
|
+
require 'trace_visualization/repetitions_context'
|
3
|
+
require 'trace_visualization/data/repetition'
|
4
|
+
|
5
|
+
describe TraceVisualization::RepetitionsConcatenation do
|
6
|
+
it "process common positions" do
|
7
|
+
str = "aaaxbbbyaaazbbbvaaawbbb"
|
8
|
+
|
9
|
+
context = TraceVisualization::Repetitions::Context.new(str, [])
|
10
|
+
|
11
|
+
lpos = [0, 8, 16]
|
12
|
+
rpos = [4, 12, 20]
|
13
|
+
ppos = [[0, 4], [8, 12], [16, 20]]
|
14
|
+
|
15
|
+
left = TraceVisualization::Data::Repetition.new(3, lpos)
|
16
|
+
right = TraceVisualization::Data::Repetition.new(3, rpos)
|
17
|
+
|
18
|
+
cpl, cpr = TraceVisualization::RepetitionsConcatenation.process_common_positions(left, right, 1, context)
|
19
|
+
|
20
|
+
left.left_positions.should eq cpl
|
21
|
+
right.left_positions.should eq cpr
|
22
|
+
|
23
|
+
lpos.should eq left.left_positions
|
24
|
+
rpos.should eq right.left_positions
|
25
|
+
end
|
26
|
+
|
27
|
+
it "don't concatenate repetitions through forbidden chars" do
|
28
|
+
str = <<EOF
|
29
|
+
aaa
|
30
|
+
bbb
|
31
|
+
aaa
|
32
|
+
bbb
|
33
|
+
EOF
|
34
|
+
context = TraceVisualization::Repetitions::Context.new(str, [])
|
35
|
+
|
36
|
+
lpos, rpos = [0, 8], [4, 12]
|
37
|
+
left = TraceVisualization::Data::Repetition.new(3, lpos)
|
38
|
+
right = TraceVisualization::Data::Repetition.new(3, rpos)
|
39
|
+
|
40
|
+
cpl, cpr = TraceVisualization::RepetitionsConcatenation.process_common_positions(left, right, 1, context)
|
41
|
+
|
42
|
+
cpl.should eq []
|
43
|
+
cpr.should eq []
|
44
|
+
|
45
|
+
#
|
46
|
+
str.gsub!(TraceVisualization::FORBIDDEN_CHARS, "x")
|
47
|
+
context = TraceVisualization::Repetitions::Context.new(str, [])
|
48
|
+
|
49
|
+
lpos, rpos = [0, 8], [4, 12]
|
50
|
+
left = TraceVisualization::Data::Repetition.new(3, lpos)
|
51
|
+
right = TraceVisualization::Data::Repetition.new(3, rpos)
|
52
|
+
|
53
|
+
cpl, cpr = TraceVisualization::RepetitionsConcatenation.process_common_positions(left, right, 1, context)
|
54
|
+
|
55
|
+
cpl.should eq [0, 8]
|
56
|
+
cpr.should eq [4, 12]
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'trace_visualization/repetitions_incrementation'
|
2
|
+
require 'trace_visualization/data/repetition'
|
3
|
+
|
4
|
+
describe TraceVisualization::RepetitionsIncrementation do
|
5
|
+
it "simple incrementation" do
|
6
|
+
str = <<EOF
|
7
|
+
foo 12
|
8
|
+
foo 13
|
9
|
+
foo 12
|
10
|
+
foo 13
|
11
|
+
foo 12
|
12
|
+
foo 13
|
13
|
+
EOF
|
14
|
+
|
15
|
+
hashes = []
|
16
|
+
|
17
|
+
r1 = TraceVisualization::Data::Repetition.new(5, [0, 7, 14, 21, 28, 35])
|
18
|
+
r12 = TraceVisualization::Data::Repetition.new(6, [0, 14, 28])
|
19
|
+
r13 = TraceVisualization::Data::Repetition.new(6, [7, 21, 35])
|
20
|
+
|
21
|
+
repetitions = [r1, r12, r13]
|
22
|
+
|
23
|
+
TraceVisualization::RepetitionsIncrementation.incrementation(str, repetitions, hashes, 1)
|
24
|
+
|
25
|
+
repetition = repetitions[-1]
|
26
|
+
|
27
|
+
repetitions.size.should eq 4
|
28
|
+
repetition.length.should eq 6
|
29
|
+
repetition.k.should eq 1
|
30
|
+
|
31
|
+
repetition.left_positions.should eq [0, 7, 14, 21, 28, 35]
|
32
|
+
repetition.right_positions.should eq [6, 13, 20, 27, 34, 41]
|
33
|
+
end
|
34
|
+
|
35
|
+
it "left incrementation" do
|
36
|
+
str = <<EOF
|
37
|
+
12_foo
|
38
|
+
14_foo
|
39
|
+
22_foo
|
40
|
+
24_foo
|
41
|
+
30_bar
|
42
|
+
32_foo
|
43
|
+
34_foo
|
44
|
+
EOF
|
45
|
+
|
46
|
+
hashes = []
|
47
|
+
|
48
|
+
r1 = TraceVisualization::Data::Repetition.new(4, [2, 9, 16, 23, 37, 44])
|
49
|
+
r2 = TraceVisualization::Data::Repetition.new(5, [1, 15, 36])
|
50
|
+
r3 = TraceVisualization::Data::Repetition.new(5, [8, 22, 43])
|
51
|
+
|
52
|
+
repetitions = [r1, r2, r3]
|
53
|
+
|
54
|
+
TraceVisualization::RepetitionsIncrementation.incrementation(str, repetitions, hashes, 1)
|
55
|
+
|
56
|
+
repetition = repetitions[-1]
|
57
|
+
|
58
|
+
repetitions.size.should eq 4
|
59
|
+
repetition.k.should eq 1
|
60
|
+
repetition.length.should eq 5
|
61
|
+
|
62
|
+
repetition.left_positions.should eq [1, 8, 15, 22, 36, 43]
|
63
|
+
repetition.right_positions.should eq [2, 9, 16, 23, 37, 44]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "test fake repetition" do
|
67
|
+
str = <<EOF
|
68
|
+
abcde11edcb
|
69
|
+
abcde22bcde
|
70
|
+
EOF
|
71
|
+
|
72
|
+
left = TraceVisualization::Data::Repetition.new(5, [0, 12])
|
73
|
+
right = TraceVisualization::Data::Repetition.new(0, [7, 19])
|
74
|
+
|
75
|
+
repetition = TraceVisualization::Data::Repetition.new(7, [0, 12], [7, 19])
|
76
|
+
repetition.left = left
|
77
|
+
repetition.right = right
|
78
|
+
repetition.k = 2
|
79
|
+
|
80
|
+
fake = TraceVisualization::RepetitionsIncrementation.fake_repetition(
|
81
|
+
repetition.class, repetition.left_positions, repetition.right_positions,
|
82
|
+
"right"
|
83
|
+
)
|
84
|
+
|
85
|
+
right.left_positions.should eq fake.left_positions
|
86
|
+
right.right_positions.should eq fake.right_positions
|
87
|
+
end
|
88
|
+
end
|