coopy 0.6.4.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +7 -0
- data/LICENSE.md +22 -0
- data/README.md +59 -0
- data/Rakefile +4 -6
- data/coopy.gemspec +26 -0
- data/lib/coopy.rb +32 -175
- data/lib/coopy/alignment.rb +260 -0
- data/lib/coopy/bag.rb +17 -0
- data/lib/coopy/cell_info.rb +24 -0
- data/lib/coopy/change_type.rb +10 -0
- data/lib/coopy/compare_flags.rb +62 -0
- data/lib/coopy/compare_table.rb +327 -0
- data/lib/coopy/coopy.rb +22 -0
- data/lib/coopy/cross_match.rb +10 -0
- data/lib/coopy/csv_table.rb +51 -0
- data/lib/coopy/diff_render.rb +307 -0
- data/lib/coopy/index.rb +73 -0
- data/lib/coopy/index_item.rb +17 -0
- data/lib/coopy/index_pair.rb +72 -0
- data/lib/coopy/mover.rb +123 -0
- data/lib/coopy/ordering.rb +27 -0
- data/lib/coopy/row.rb +9 -0
- data/lib/coopy/simple_cell.rb +15 -0
- data/lib/coopy/simple_table.rb +144 -0
- data/lib/coopy/simple_view.rb +36 -0
- data/lib/coopy/table.rb +44 -0
- data/lib/coopy/table_comparison_state.rb +33 -0
- data/lib/coopy/table_diff.rb +634 -0
- data/lib/coopy/table_text.rb +14 -0
- data/lib/coopy/table_view.rb +31 -0
- data/lib/coopy/unit.rb +53 -0
- data/lib/coopy/version.rb +3 -0
- data/lib/coopy/view.rb +34 -0
- data/spec/fixtures/bridges.html +10 -0
- data/spec/fixtures/bridges_diff.csv +8 -0
- data/spec/fixtures/bridges_new.csv +9 -0
- data/spec/fixtures/bridges_old.csv +9 -0
- data/spec/fixtures/planetary_bodies.html +22 -0
- data/spec/fixtures/planetary_bodies_diff.csv +19 -0
- data/spec/fixtures/planetary_bodies_new.csv +20 -0
- data/spec/fixtures/planetary_bodies_old.csv +19 -0
- data/spec/fixtures/quote_me.csv +10 -0
- data/spec/fixtures/quote_me2.csv +11 -0
- data/spec/integration/table_diff_spec.rb +57 -0
- data/spec/libs/compare_flags_spec.rb +40 -0
- data/spec/libs/coopy_spec.rb +14 -0
- data/spec/libs/ordering_spec.rb +28 -0
- data/spec/libs/unit_spec.rb +31 -0
- data/spec/spec_helper.rb +29 -0
- metadata +153 -46
- data/bin/sqlite_diff +0 -4
- data/bin/sqlite_patch +0 -4
- data/bin/sqlite_rediff +0 -4
- data/lib/coopy/dbi_sql_wrapper.rb +0 -89
- data/lib/coopy/diff_apply_sql.rb +0 -35
- data/lib/coopy/diff_columns.rb +0 -33
- data/lib/coopy/diff_output.rb +0 -21
- data/lib/coopy/diff_output_action.rb +0 -34
- data/lib/coopy/diff_output_group.rb +0 -40
- data/lib/coopy/diff_output_raw.rb +0 -17
- data/lib/coopy/diff_output_stats.rb +0 -45
- data/lib/coopy/diff_output_table.rb +0 -49
- data/lib/coopy/diff_output_tdiff.rb +0 -48
- data/lib/coopy/diff_parser.rb +0 -92
- data/lib/coopy/diff_render_csv.rb +0 -29
- data/lib/coopy/diff_render_html.rb +0 -74
- data/lib/coopy/diff_render_log.rb +0 -52
- data/lib/coopy/row_change.rb +0 -25
- data/lib/coopy/scraperwiki_sql_wrapper.rb +0 -8
- data/lib/coopy/scraperwiki_utils.rb +0 -23
- data/lib/coopy/sequel_sql_wrapper.rb +0 -73
- data/lib/coopy/sql_compare.rb +0 -222
- data/lib/coopy/sql_wrapper.rb +0 -34
- data/lib/coopy/sqlite_sql_wrapper.rb +0 -143
- data/test/test_coopy.rb +0 -126
@@ -0,0 +1,31 @@
|
|
1
|
+
module Coopy
|
2
|
+
class TableView
|
3
|
+
include Coopy::View
|
4
|
+
|
5
|
+
def to_s(d)
|
6
|
+
d.to_s
|
7
|
+
end
|
8
|
+
|
9
|
+
def get_bag(d)
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_table(d)
|
14
|
+
d
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_structure?(d)
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def equals(d1, d2)
|
22
|
+
puts("TableView#equals called")
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_datum(str)
|
27
|
+
Coopy::SimpleCell.new(str)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
data/lib/coopy/unit.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
module Coopy
|
2
|
+
|
3
|
+
class Unit
|
4
|
+
|
5
|
+
attr_accessor :l # integer
|
6
|
+
attr_accessor :r # integer
|
7
|
+
attr_accessor :p # integer
|
8
|
+
|
9
|
+
def initialize(l = -2, r = -2, p = -2)
|
10
|
+
@l = l;
|
11
|
+
@r = r;
|
12
|
+
@p = p;
|
13
|
+
end
|
14
|
+
|
15
|
+
def lp
|
16
|
+
(@p==-2) ? @l : @p
|
17
|
+
end
|
18
|
+
|
19
|
+
def describe(i)
|
20
|
+
(i>=0) ? ("" + i.to_s) : "-"
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
return describe(@p) + "|" + describe(@l) + ":" + describe(@r) if (@p>=-1)
|
25
|
+
describe(@l) + ":" + describe(@r)
|
26
|
+
end
|
27
|
+
|
28
|
+
def from_string(txt)
|
29
|
+
txt += "]"
|
30
|
+
at = 0
|
31
|
+
txt.each_char do |ch|
|
32
|
+
case ch
|
33
|
+
when /[0-9]/
|
34
|
+
at *= 10;
|
35
|
+
at += ch.to_i
|
36
|
+
when '-'
|
37
|
+
at = -1
|
38
|
+
when '|'
|
39
|
+
@p = at
|
40
|
+
at = 0
|
41
|
+
when ':'
|
42
|
+
@l = at
|
43
|
+
at = 0
|
44
|
+
when ']'
|
45
|
+
@r = at
|
46
|
+
return true
|
47
|
+
end
|
48
|
+
end
|
49
|
+
false
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
data/lib/coopy/view.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
module Coopy
|
2
|
+
|
3
|
+
# Optimize access to arrays of primitives, avoid needing
|
4
|
+
# each item to be wrapped individually in some kind of access object.
|
5
|
+
# Anticipate future optimization with view pools.
|
6
|
+
|
7
|
+
module View
|
8
|
+
|
9
|
+
def to_s(d)
|
10
|
+
raise NotImplementedError
|
11
|
+
end
|
12
|
+
|
13
|
+
def get_bag(d)
|
14
|
+
raise NotImplementedError
|
15
|
+
end
|
16
|
+
|
17
|
+
def get_table(d)
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_structure?(d)
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
def equals(d1, d2)
|
26
|
+
raise NotImplementedError
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_datum(str)
|
30
|
+
raise NotImplementedError
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<table>
|
2
|
+
<tr><th>@@</th><th>bridge</th><th>designer</th><th>length</th></tr>
|
3
|
+
<tr><td></td><td>Brooklyn</td><td>J. A. Roebling</td><td>1595</td></tr>
|
4
|
+
<tr class="add"><td>+++</td><td>Manhattan</td><td>G. Lindenthal</td><td>1470</td></tr>
|
5
|
+
<tr class="modify"><td class="modify">→</td><td>Williamsburg</td><td class="modify">D. Duck→L. L. Buck</td><td>1600</td></tr>
|
6
|
+
<tr><td></td><td>Queensborough</td><td>Palmer & Hornbostel</td><td>1182</td></tr>
|
7
|
+
<tr><td>...</td><td>...</td><td>...</td><td>...</td></tr>
|
8
|
+
<tr><td></td><td>George Washington</td><td>O. H. Ammann</td><td>3500</td></tr>
|
9
|
+
<tr class="remove"><td>---</td><td>Spamspan</td><td>S. Spamington</td><td>10000</td></tr>
|
10
|
+
</table>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
@@,bridge,designer,length
|
2
|
+
NULL,Brooklyn,"J. A. Roebling",1595
|
3
|
+
+++,Manhattan,"G. Lindenthal",1470
|
4
|
+
->,Williamsburg,"D. Duck->L. L. Buck",1600
|
5
|
+
NULL,Queensborough,"Palmer & Hornbostel",1182
|
6
|
+
...,...,...,...
|
7
|
+
NULL,"George Washington","O. H. Ammann",3500
|
8
|
+
---,Spamspan,"S. Spamington",10000
|
@@ -0,0 +1,9 @@
|
|
1
|
+
bridge,designer,length
|
2
|
+
Brooklyn,J. A. Roebling,1595
|
3
|
+
Manhattan,G. Lindenthal,1470
|
4
|
+
Williamsburg,L. L. Buck,1600
|
5
|
+
Queensborough,Palmer & Hornbostel,1182
|
6
|
+
Triborough,O. H. Ammann,"1380,383"
|
7
|
+
Bronx Whitestone,O. H. Ammann,2300
|
8
|
+
Throgs Neck,O. H. Ammann,1800
|
9
|
+
George Washington,O. H. Ammann,3500
|
@@ -0,0 +1,9 @@
|
|
1
|
+
bridge,designer,length
|
2
|
+
Brooklyn,J. A. Roebling,1595
|
3
|
+
Williamsburg,D. Duck,1600
|
4
|
+
Queensborough,Palmer & Hornbostel,1182
|
5
|
+
Triborough,O. H. Ammann,"1380,383"
|
6
|
+
Bronx Whitestone,O. H. Ammann,2300
|
7
|
+
Throgs Neck,O. H. Ammann,1800
|
8
|
+
George Washington,O. H. Ammann,3500
|
9
|
+
Spamspan,S. Spamington,10000
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<table>
|
2
|
+
<tr class="spec"><td>!</td><td></td><td class="add">+++</td><td></td></tr>
|
3
|
+
<tr><th>@@</th><th>planetary_body</th><th class="add">aphelion</th><th>acceleration</th></tr>
|
4
|
+
<tr><td>+</td><td>Earth</td><td class="add">152098232</td><td>9.80665</td></tr>
|
5
|
+
<tr><td></td><td>Moon</td><td class="add"></td><td>1.625</td></tr>
|
6
|
+
<tr><td>+</td><td>Sun</td><td class="add">0</td><td>274.1</td></tr>
|
7
|
+
<tr class="add"><td>+++</td><td>Mercury</td><td class="add">69816900</td><td>3.7</td></tr>
|
8
|
+
<tr><td>+</td><td>Venus</td><td class="add">108939000</td><td>8.872</td></tr>
|
9
|
+
<tr><td>+</td><td>Mars</td><td class="add">249209300</td><td>3.78</td></tr>
|
10
|
+
<tr><td>+</td><td>Jupiter</td><td class="add">816520800</td><td>25.93</td></tr>
|
11
|
+
<tr><td></td><td>Io</td><td class="add"></td><td>1.789</td></tr>
|
12
|
+
<tr><td>...</td><td>...</td><td class="add">...</td><td>...</td></tr>
|
13
|
+
<tr><td></td><td>Callisto</td><td class="add"></td><td>1.24</td></tr>
|
14
|
+
<tr><td>+</td><td>Saturn</td><td class="add">1513325783</td><td>11.19</td></tr>
|
15
|
+
<tr><td></td><td>Titan</td><td class="add"></td><td>1.3455</td></tr>
|
16
|
+
<tr><td>+</td><td>Uranus</td><td class="add">3004419704</td><td>9.01</td></tr>
|
17
|
+
<tr><td></td><td>Titania</td><td class="add"></td><td>0.379</td></tr>
|
18
|
+
<tr><td></td><td>Oberon</td><td class="add"></td><td>0.347</td></tr>
|
19
|
+
<tr><td>+</td><td>Neptune</td><td class="add">4553946490</td><td>11.28</td></tr>
|
20
|
+
<tr class="modify"><td class="modify">→</td><td>Triton</td><td class="add"></td><td class="modify"> 0.779→0.779</td></tr>
|
21
|
+
<tr class="modify"><td class="modify">→</td><td>Pluto</td><td class="add">7311000000</td><td class="modify"> 0.61→0.61</td></tr>
|
22
|
+
</table>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
!,NULL,+++,NULL
|
2
|
+
@@,planetary_body,aphelion,acceleration
|
3
|
+
+,Earth,152098232,9.80665
|
4
|
+
NULL,Moon,NULL,1.625
|
5
|
+
+,Sun,0,274.1
|
6
|
+
+++,Mercury,69816900,3.7
|
7
|
+
+,Venus,108939000,8.872
|
8
|
+
+,Mars,249209300,3.78
|
9
|
+
+,Jupiter,816520800,25.93
|
10
|
+
NULL,Io,NULL,1.789
|
11
|
+
...,...,...,...
|
12
|
+
NULL,Callisto,NULL,1.24
|
13
|
+
+,Saturn,1513325783,11.19
|
14
|
+
NULL,Titan,NULL,1.3455
|
15
|
+
+,Uranus,3004419704,9.01
|
16
|
+
NULL,Titania,NULL,0.379
|
17
|
+
NULL,Oberon,NULL,0.347
|
18
|
+
+,Neptune,4553946490,11.28
|
19
|
+
->,Triton,NULL," 0.779->0.779"
|
@@ -0,0 +1,20 @@
|
|
1
|
+
planetary_body,aphelion,acceleration
|
2
|
+
"Earth",152098232,9.80665
|
3
|
+
"Moon",,1.625
|
4
|
+
"Sun",0,274.1
|
5
|
+
"Mercury",69816900,3.7
|
6
|
+
"Venus",108939000,8.872
|
7
|
+
"Mars",249209300,3.78
|
8
|
+
"Jupiter",816520800,25.93
|
9
|
+
"Io",,1.789
|
10
|
+
"Europa",,1.314
|
11
|
+
"Ganymede",,1.426
|
12
|
+
"Callisto",,1.24
|
13
|
+
"Saturn",1513325783,11.19
|
14
|
+
"Titan",,1.3455
|
15
|
+
"Uranus",3004419704,9.01
|
16
|
+
"Titania",,0.379
|
17
|
+
"Oberon",,0.347
|
18
|
+
"Neptune",4553946490,11.28
|
19
|
+
"Triton",,0.779
|
20
|
+
"Pluto",7311000000,0.61
|
@@ -0,0 +1,19 @@
|
|
1
|
+
planetary_body,acceleration
|
2
|
+
"Earth",9.80665
|
3
|
+
"Moon",1.625
|
4
|
+
"Sun",274.1
|
5
|
+
"Venus",8.872
|
6
|
+
"Mars",3.78
|
7
|
+
"Jupiter",25.93
|
8
|
+
"Io",1.789
|
9
|
+
"Europa",1.314
|
10
|
+
"Ganymede",1.426
|
11
|
+
"Callisto",1.24
|
12
|
+
"Saturn",11.19
|
13
|
+
"Titan",1.3455
|
14
|
+
"Uranus",9.01
|
15
|
+
"Titania",0.379
|
16
|
+
"Oberon",0.347
|
17
|
+
"Neptune",11.28
|
18
|
+
"Triton", 0.779
|
19
|
+
"Pluto", 0.61
|
@@ -0,0 +1,10 @@
|
|
1
|
+
this,is,a,sheet
|
2
|
+
with,some,odd,values
|
3
|
+
in,cells,"->",":"
|
4
|
+
you,"see?","123""",
|
5
|
+
what,about null,NULL,_NULL
|
6
|
+
and,"new
|
7
|
+
lines","how, really,
|
8
|
+
about","them?"
|
9
|
+
"and 'embedded'","quotes it's","fun","""fun"""
|
10
|
+
"!HELLO!","my!","!friend","the!exclamation!mark"
|
@@ -0,0 +1,11 @@
|
|
1
|
+
this,is,a,sheet
|
2
|
+
with,some,odd,values
|
3
|
+
in,"->",cells,"bob | mcdonald"
|
4
|
+
you,"see?...","Indeed",
|
5
|
+
what,about NULL,_NULL,NULL
|
6
|
+
and,"new
|
7
|
+
so very new
|
8
|
+
lines","how
|
9
|
+
about","them?"
|
10
|
+
"and 'embedded'","'quotes' it's","'fun'","fun"
|
11
|
+
"!!HELLO!!","my","!friend","the!!exclamationmark"
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "diffing tables" do
|
4
|
+
|
5
|
+
[
|
6
|
+
"bridges",
|
7
|
+
"planetary_bodies",
|
8
|
+
].each do |name|
|
9
|
+
|
10
|
+
it "should generate correct diff for #{name}" do
|
11
|
+
|
12
|
+
old_table = Coopy::CsvTable.new(CSV.parse(load_fixture("#{name}_old.csv")))
|
13
|
+
new_table = Coopy::CsvTable.new(CSV.parse(load_fixture("#{name}_new.csv")))
|
14
|
+
|
15
|
+
alignment = Coopy.compare_tables(old_table,new_table).align
|
16
|
+
|
17
|
+
table_diff = Coopy::SimpleTable.new(0,0)
|
18
|
+
|
19
|
+
flags = Coopy::CompareFlags.new
|
20
|
+
highlighter = Coopy::TableDiff.new(alignment,flags)
|
21
|
+
highlighter.hilite table_diff
|
22
|
+
|
23
|
+
expected_diff = CSV.parse(load_fixture("#{name}_diff.csv"))
|
24
|
+
expected_diff.each_with_index do |row, row_index|
|
25
|
+
row.each_with_index do |cell, col_index|
|
26
|
+
expected = table_diff.get_cell(col_index, row_index).to_s
|
27
|
+
got = cell.to_s
|
28
|
+
got = '' if got == "NULL"
|
29
|
+
expected.should eql(got), "row:#{row_index} col:#{col_index} was '#{got}' instead of '#{expected}'"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should generate correct HTML for #{name}" do
|
36
|
+
|
37
|
+
old_table = Coopy::CsvTable.new(CSV.parse(load_fixture("#{name}_old.csv")))
|
38
|
+
new_table = Coopy::CsvTable.new(CSV.parse(load_fixture("#{name}_new.csv")))
|
39
|
+
|
40
|
+
alignment = Coopy.compare_tables(old_table,new_table).align
|
41
|
+
|
42
|
+
table_diff = Coopy::SimpleTable.new(0,0)
|
43
|
+
|
44
|
+
flags = Coopy::CompareFlags.new
|
45
|
+
highlighter = Coopy::TableDiff.new(alignment,flags)
|
46
|
+
highlighter.hilite table_diff
|
47
|
+
|
48
|
+
diff2html = Coopy::DiffRender.new
|
49
|
+
diff2html.render table_diff
|
50
|
+
diff_html = diff2html.html
|
51
|
+
|
52
|
+
diff_html.should == load_fixture("#{name}.html")
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coopy::CompareFlags do
|
4
|
+
|
5
|
+
context "action settings" do
|
6
|
+
|
7
|
+
it "should allow all by default" do
|
8
|
+
flags = Coopy::CompareFlags.new
|
9
|
+
flags.allow_update.should be_true
|
10
|
+
flags.allow_insert.should be_true
|
11
|
+
flags.allow_delete.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow update if set" do
|
15
|
+
flags = Coopy::CompareFlags.new
|
16
|
+
flags.acts = {"update" => true}
|
17
|
+
flags.allow_update.should be_true
|
18
|
+
flags.allow_insert.should be_false
|
19
|
+
flags.allow_delete.should be_false
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should allow insert if set" do
|
23
|
+
flags = Coopy::CompareFlags.new
|
24
|
+
flags.acts = {"insert" => true}
|
25
|
+
flags.allow_update.should be_false
|
26
|
+
flags.allow_insert.should be_true
|
27
|
+
flags.allow_delete.should be_false
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should allow delete if set" do
|
31
|
+
flags = Coopy::CompareFlags.new
|
32
|
+
flags.acts = {"delete" => true}
|
33
|
+
flags.allow_update.should be_false
|
34
|
+
flags.allow_insert.should be_false
|
35
|
+
flags.allow_delete.should be_true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coopy::Ordering do
|
4
|
+
|
5
|
+
it "should convert order to string correctly" do
|
6
|
+
# test default behaviour
|
7
|
+
o = Coopy::Ordering.new
|
8
|
+
o.to_s.should == ''
|
9
|
+
# add a couple of units
|
10
|
+
o.add 1,2,3
|
11
|
+
o.add 3,2,1
|
12
|
+
o.to_s.should == "3|1:2, 1|3:2"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should not ignore parent if not set" do
|
16
|
+
o = Coopy::Ordering.new
|
17
|
+
o.add 1,2,3
|
18
|
+
o.to_s.should == "3|1:2"
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should ignore parent if set" do
|
22
|
+
o = Coopy::Ordering.new
|
23
|
+
o.ignore_parent
|
24
|
+
o.add 1,2,3
|
25
|
+
o.to_s.should == "1:2"
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coopy::Unit do
|
4
|
+
|
5
|
+
context "string conversion" do
|
6
|
+
|
7
|
+
[
|
8
|
+
[3,2,1],
|
9
|
+
[1,2,3],
|
10
|
+
[1,2,-2],
|
11
|
+
[3,2,-1],
|
12
|
+
[0,1,0],
|
13
|
+
].each do |lrp|
|
14
|
+
|
15
|
+
it "should marshall strings in and out correctly (#{lrp.to_s})" do
|
16
|
+
|
17
|
+
u = Coopy::Unit.new lrp[0], lrp[1], lrp[2]
|
18
|
+
str = u.to_s
|
19
|
+
|
20
|
+
nu = Coopy::Unit.new
|
21
|
+
nu.from_string(str).should be_true
|
22
|
+
|
23
|
+
u.l.should == nu.l
|
24
|
+
u.r.should == nu.r
|
25
|
+
u.p.should == nu.p
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|