sp-squealer 1.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.
@@ -0,0 +1,166 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/./spec_helper_dbms')
2
+
3
+ describe Squealer::Database do
4
+ it "is a singleton" do
5
+ Squealer::Database.respond_to?(:instance).should be_true
6
+ end
7
+
8
+ describe "import" do
9
+ let(:databases) { Squealer::Database.instance }
10
+
11
+
12
+ it "takes an import database" do
13
+ databases.send(:instance_variable_get, '@import_dbc').should be_a_kind_of(Mongo::DB)
14
+ end
15
+
16
+ it "returns a squealer connection object" do
17
+ databases.import.should be_a_kind_of(Squealer::Database::Connection)
18
+ end
19
+
20
+ it "delegates eval to Mongo" do
21
+ databases.send(:instance_variable_get, '@import_dbc').eval('db.getName()').should == $db_name
22
+ databases.import.eval('db.getName()').should == $db_name
23
+ end
24
+ end
25
+
26
+ describe "source" do
27
+ let(:databases) { Squealer::Database.instance }
28
+
29
+ before { databases.import_from('localhost', 27017, $db_name) }
30
+
31
+ it "returns a Source" do
32
+ databases.import.source('foo').should be_a_kind_of(Squealer::Database::Source)
33
+ end
34
+
35
+ describe "Source::cursor" do
36
+ it "returns a databases cursor" do
37
+ databases.import.source('foo').cursor.should be_a_kind_of(Mongo::Cursor)
38
+ end
39
+ end
40
+
41
+ context "an empty collection" do
42
+ subject { databases.import.source('foo') }
43
+
44
+ it "counts a total of zero" do
45
+ subject.counts[:total].should == 0
46
+ end
47
+
48
+ it "counts zero imported" do
49
+ subject.counts[:imported].should == 0
50
+ end
51
+
52
+ it "counts zero exported" do
53
+ subject.counts[:exported].should == 0
54
+ end
55
+ end
56
+
57
+ context "a collection with two documents" do
58
+ let(:mongo) { Squealer::Database.instance.import.send(:instance_variable_get, '@dbc') }
59
+
60
+ subject do
61
+ mongo.collection('foo').save({'name' => 'Bar'});
62
+ mongo.collection('foo').save({'name' => 'Baz'});
63
+ source = databases.import.source('foo') # activate the counter
64
+ source.send(:instance_variable_set, :@progress_bar, nil)
65
+ Squealer::ProgressBar.send(:class_variable_set, :@@progress_bar, nil)
66
+ source
67
+ end
68
+
69
+ after do
70
+ mongo.collection('foo').drop
71
+ end
72
+
73
+ it "returns a Source" do
74
+ subject.should be_a_kind_of(Squealer::Database::Source)
75
+ end
76
+
77
+ it "counts a total of two" do
78
+ subject.counts[:total].should == 2
79
+ end
80
+
81
+ context "before iterating" do
82
+ it "counts zero imported" do
83
+ subject.counts[:imported].should == 0
84
+ end
85
+
86
+ it "counts zero exported" do
87
+ subject.counts[:exported].should == 0
88
+ end
89
+ end
90
+
91
+ context "after iterating" do
92
+ before do
93
+ subject.each {}
94
+ end
95
+
96
+ it "counts two imported" do
97
+ subject.counts[:imported].should == 2
98
+ end
99
+
100
+ it "counts two exported" do
101
+ subject.counts[:exported].should == 2
102
+ end
103
+ end
104
+
105
+ context "real squeal" do
106
+ # before { pending "interactive_view" }
107
+ it "exports that stuff to SQL" do
108
+ databases.export_to($do_adapter, 'localhost', $do_user, $do_pass, $db_name)
109
+ databases.import.source("users").each do |user|
110
+ target(:user) do |target|
111
+ target.instance_variable_get('@row_id').should == user['_id'].to_s
112
+ assign(:organization_id)
113
+ assign(:name)
114
+
115
+ #TODO: Update README to highlight that all embedded docs should have an _id
116
+ # as all Ruby mappers for MongoDB make one. (according to Durran)
117
+ user.activities.each do |activity|
118
+ target(:activity) do |target|
119
+ assign(:user_id)
120
+ assign(:name)
121
+ assign(:due_date)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+
129
+ end
130
+
131
+ end
132
+
133
+ describe "export" do
134
+ let(:databases) { Squealer::Database.instance }
135
+
136
+ it "creates a DataObjects connection to the export database" do
137
+ databases.export_to($do_adapter, 'localhost', $do_user, $do_pass, $db_name)
138
+ databases.instance_variable_get('@export_do').should be_a_kind_of DataObjects::Connection
139
+ end
140
+ end
141
+
142
+ describe "upsertable?" do
143
+ subject { Squealer::Database.instance }
144
+
145
+ if defined?(DataObjects::Mysql)
146
+ context "mysql connection" do
147
+ before do
148
+ subject.export_to('mysql', 'localhost', $do_user, $do_pass, 'mysql')
149
+ end
150
+
151
+ it { should be_upsertable }
152
+ end
153
+ end
154
+
155
+ if defined?(DataObjects::Postgres)
156
+ context "postgres connection" do
157
+ before do
158
+ subject.export_to('postgres', 'localhost', $do_user, $do_pass, 'postgres')
159
+ end
160
+
161
+ it { should_not be_upsertable }
162
+ end
163
+ end
164
+ end
165
+
166
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+ require File.expand_path(File.dirname(__FILE__) + "/./spec_helper_dbms_#{ENV['EXPORT_DBMS']||'mysql'}")
3
+
4
+ Spec::Runner.configure do |config|
5
+ config.before(:suite) do
6
+ $db_name = "squealer_test_export_#{object_id}"
7
+ create_export_db($db_name)
8
+ create_import_db($db_name)
9
+ end
10
+
11
+ config.after(:suite) do
12
+ DataObjects::Pooling.pools.each {|pool| pool.flush!}
13
+ drop_export_test_db($db_name)
14
+
15
+ drop_mongo
16
+ end
17
+
18
+ config.before(:each) do
19
+ if self.class.example_implementations.first.first.location =~ %r{/spec/integration/}
20
+ Squealer::Database.instance.export_to($do_adapter, $do_host, $do_user, $do_pass, $db_name)
21
+ truncate_export_tables(Squealer::Database.instance.export)
22
+ end
23
+ end
24
+ config.after(:each) do
25
+ if self.class.example_implementations.first.first.location =~ %r{/spec/integration/}
26
+ Squealer::Database.instance.export.release
27
+ end
28
+ end
29
+ end
30
+
31
+ def create_import_db(name)
32
+ Squealer::Database.instance.import_from('localhost', 27017, name)
33
+ @mongo = Squealer::Database.instance.import.instance_variable_get('@dbc')
34
+ drop_mongo
35
+ seed_import
36
+ end
37
+
38
+ def drop_mongo
39
+ @mongo.eval('db.dropDatabase()') if @mongo
40
+ end
41
+
42
+ def seed_import
43
+ hashrocket = @mongo.collection('organizations').save({ :name => 'Hashrocket' })
44
+ zorganization = @mongo.collection('organizations').save({ :name => 'Zorganization', :disabled_date => as_time(Date.today) })
45
+
46
+ users = [
47
+ { :name => 'Josh Graham', :dob => as_time(Date.parse('01-Jan-1971')), :gender => 'M',
48
+ :organization_id => hashrocket,
49
+ :activities => [
50
+ { :_id => id, :name => 'Develop squealer', :due_date => as_time(Date.today + 1) },
51
+ { :_id => id, :name => 'Organize speakerconf.com', :due_date => as_time(Date.today + 30) },
52
+ { :_id => id, :name => 'Hashrocket party', :due_date => as_time(Date.today + 7) }
53
+ ]
54
+ },
55
+ { :name => 'Bernerd Schaefer', :dob => as_time(Date.parse('31-Dec-1985')), :gender => 'M',
56
+ :organization_id => hashrocket,
57
+ :activities => [
58
+ { :_id => id, :name => 'Retype all of the code Josh wrote in squealer', :due_date => as_time(Date.today + 2) },
59
+ { :_id => id, :name => 'Listen to rare Thelonius Monk EP', :due_date => as_time(Date.today) },
60
+ { :_id => id, :name => 'Practice karaoke', :due_date => as_time(Date.today + 7) }
61
+ ]
62
+ },
63
+ { :name => 'Your momma', :dob => as_time(Date.parse('15-Jun-1955')), :gender => 'F',
64
+ :organization_id => zorganization,
65
+ :activities => [
66
+ { :_id => id, :name => 'Cook me some pie', :due_date => as_time(Date.today) },
67
+ { :_id => id, :name => 'Make me a sammich', :due_date => as_time(Date.today) }
68
+ ]
69
+ }
70
+ ]
71
+
72
+ users.each { |user| @mongo.collection('users').save user }
73
+ end
74
+
75
+
76
+ def truncate_export_tables(dbc)
77
+ %w{user activity organization}.each do |t|
78
+ text = %{TRUNCATE TABLE "#{t}"}
79
+ dbc.create_command(text).execute_non_query
80
+ end
81
+ end
82
+
83
+ def non_query(text)
84
+ dbc = do_conn
85
+ dbc.create_command(text).execute_non_query
86
+ dbc.release
87
+ end
88
+
89
+ def drop_export_test_db(name)
90
+ dbc = do_conn_default
91
+ dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
92
+ dbc.release
93
+ end
94
+
95
+ def do_conn
96
+ DataObjects::Connection.new("#{$do_adapter}://#{at_host}/#{$db_name}")
97
+ end
98
+
99
+ def do_conn_default
100
+ DataObjects::Connection.new("#{$do_adapter}://#{at_host}/#{$do_adapter}")
101
+ end
102
+
103
+ def at_host
104
+ creds = ""
105
+ creds << $do_user if $do_user
106
+ creds << ":#{$do_pass}" if $do_pass
107
+
108
+ at_host = ""
109
+ at_host << "#{creds}@" unless creds.empty?
110
+ at_host << $do_host
111
+ end
@@ -0,0 +1,50 @@
1
+ require 'do_mysql'
2
+
3
+ $do_adapter = 'mysql'
4
+ $do_host = 'localhost'
5
+ $do_user = 'root'
6
+ $do_pass = ''
7
+
8
+ def create_export_db(name)
9
+ dbc = do_conn_default
10
+ dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
11
+ dbc.create_command("CREATE DATABASE #{name}").execute_non_query
12
+ dbc.create_command("SET sql_mode='ANSI_QUOTES'").execute_non_query
13
+ dbc.release
14
+ create_export_tables
15
+ end
16
+
17
+ def create_export_tables
18
+ command = <<-COMMAND.gsub(/\n\s*/, " ")
19
+ CREATE TABLE "user" (
20
+ "id" CHAR(24) NOT NULL ,
21
+ "organization_id" CHAR(24) NOT NULL ,
22
+ "name" VARCHAR(255) NULL ,
23
+ "gender" CHAR(1) NULL ,
24
+ "dob" DATETIME NULL ,
25
+ "foreign" BOOLEAN NULL ,
26
+ "dull" BOOLEAN NULL ,
27
+ "symbolic" VARCHAR(255) NULL ,
28
+ "interests" TEXT NULL ,
29
+ PRIMARY KEY ("id") )
30
+ COMMAND
31
+ non_query(command)
32
+
33
+ command = <<-COMMAND.gsub(/\n\s*/, " ")
34
+ CREATE TABLE "activity" (
35
+ "id" CHAR(24) NOT NULL ,
36
+ "user_id" CHAR(24) NULL ,
37
+ "name" VARCHAR(255) NULL ,
38
+ "due_date" DATETIME NULL ,
39
+ PRIMARY KEY ("id") )
40
+ COMMAND
41
+ non_query(command)
42
+
43
+ command = <<-COMMAND.gsub(/\n\s*/, " ")
44
+ CREATE TABLE "organization" (
45
+ "id" CHAR(24) NOT NULL ,
46
+ "disabled_date" DATETIME NULL ,
47
+ PRIMARY KEY ("id") )
48
+ COMMAND
49
+ non_query(command)
50
+ end
@@ -0,0 +1,49 @@
1
+ require 'do_postgres'
2
+
3
+ $do_adapter = 'postgres'
4
+ $do_host = 'localhost'
5
+ $do_user = nil
6
+ $do_pass = nil
7
+
8
+ def create_export_db(name)
9
+ dbc = do_conn_default
10
+ dbc.create_command("DROP DATABASE IF EXISTS #{name}").execute_non_query
11
+ dbc.create_command("CREATE DATABASE #{name}").execute_non_query
12
+ dbc.release
13
+ create_export_tables
14
+ end
15
+
16
+ def create_export_tables
17
+ command = <<-COMMAND.gsub(/\n\s*/, " ")
18
+ CREATE TABLE "user" (
19
+ "id" CHAR(24) NOT NULL ,
20
+ "organization_id" CHAR(24) NOT NULL ,
21
+ "name" VARCHAR(255) NULL ,
22
+ "gender" CHAR(1) NULL ,
23
+ "dob" TIMESTAMP NULL ,
24
+ "foreign" BOOLEAN NULL ,
25
+ "dull" BOOLEAN NULL ,
26
+ "symbolic" VARCHAR(255) NULL ,
27
+ "interests" TEXT NULL ,
28
+ PRIMARY KEY ("id") )
29
+ COMMAND
30
+ non_query(command)
31
+
32
+ command = <<-COMMAND.gsub(/\n\s*/, " ")
33
+ CREATE TABLE "activity" (
34
+ "id" CHAR(24) NOT NULL ,
35
+ "user_id" CHAR(24) NULL ,
36
+ "name" VARCHAR(255) NULL ,
37
+ "due_date" TIMESTAMP NULL ,
38
+ PRIMARY KEY ("id") )
39
+ COMMAND
40
+ non_query(command)
41
+
42
+ command = <<-COMMAND.gsub(/\n\s*/, " ")
43
+ CREATE TABLE "organization" (
44
+ "id" CHAR(24) NOT NULL ,
45
+ "disabled_date" TIMESTAMP NULL ,
46
+ PRIMARY KEY ("id") )
47
+ COMMAND
48
+ non_query(command)
49
+ end
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format nested
3
+ --drb
@@ -0,0 +1,16 @@
1
+ require 'date'
2
+ require 'time'
3
+ require 'rubygems'
4
+
5
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ require 'squealer'
8
+
9
+ def as_time(date)
10
+ Time.parse(date.to_s)
11
+ end
12
+
13
+ def id
14
+ require 'digest/sha1'
15
+ (Digest::SHA1.hexdigest rand.to_s)[0,24]
16
+ end
@@ -0,0 +1,4 @@
1
+ require 'spec_helper'
2
+
3
+ describe Squealer::Database do
4
+ end
@@ -0,0 +1,28 @@
1
+ require "spec_helper"
2
+
3
+ describe Hash do
4
+
5
+ describe "#method_missing" do
6
+
7
+ it "treats it as a hash key lookup" do
8
+ { "name" => "Josh" }.name.should == "Josh"
9
+ end
10
+
11
+ context "with args" do
12
+
13
+ it "treats it normally" do
14
+ lambda { { "name" => "Josh" }.name(nil) }.should raise_error(NoMethodError)
15
+ end
16
+
17
+ end
18
+
19
+ context "with block" do
20
+
21
+ it "treats it normally" do
22
+ lambda { { "name" => "Josh" }.name {nil} }.should raise_error(NoMethodError)
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,119 @@
1
+ require 'spec_helper'
2
+
3
+ describe NilClass do
4
+
5
+ describe "#each" do
6
+ it "returns an empty array" do
7
+ nil.each.should == [] # because mongo is schema-less
8
+ end
9
+ end
10
+
11
+ describe "#reject" do
12
+ it "returns an empty array" do
13
+ nil.reject{false}.should == [] # because mongo is schema-less
14
+ end
15
+ end
16
+
17
+ end
18
+
19
+ describe Object do
20
+ let(:test_table) { {'_id' => 1} }
21
+
22
+ describe "#target" do
23
+
24
+ it "has been defined" do
25
+ Object.new.respond_to?(:target).should be_true
26
+ end
27
+
28
+ it "invokes Squealer::Target.new" do
29
+ Squealer::Target.should_receive(:new)
30
+ target(:test_table) { nil }
31
+ end
32
+
33
+ end
34
+
35
+ describe "#assign" do
36
+
37
+ it "has been defined" do
38
+ Object.new.respond_to?(:assign).should be_true
39
+ end
40
+
41
+ it "invokes assign on the target it is immediately nested within" do
42
+ mock_mysql
43
+ target(:test_table) do |target1|
44
+ target1.should_receive(:assign)
45
+ assign(:colA) { 42 }
46
+
47
+ test_table_2 = test_table
48
+ target(:test_table_2) do |target2|
49
+ target2.should_receive(:assign)
50
+ assign(:colspeak) { 1984 }
51
+ end
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ describe "#import" do
58
+
59
+ it "has been defined" do
60
+ Object.new.respond_to?(:import).should be_true
61
+ end
62
+
63
+ context "with a single argument" do
64
+
65
+ it "invokes Database.import_from" do
66
+ Squealer::Database.instance.should_receive(:import_from)
67
+ import('test_import')
68
+ end
69
+
70
+ end
71
+
72
+ context "with no argment" do
73
+
74
+ it "invokes Database.import" do
75
+ Squealer::Database.instance.should_receive(:import)
76
+ import
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
83
+ describe "#export" do
84
+
85
+ it "has been defined" do
86
+ Object.new.respond_to?(:export).should be_true
87
+ end
88
+
89
+ context "with a single argument" do
90
+
91
+ it "invokes Database.export_to" do
92
+ Squealer::Database.instance.should_receive(:export_to)
93
+ export('test_export')
94
+ end
95
+
96
+ end
97
+
98
+ context "with no argment" do
99
+
100
+ it "invokes Database.export" do
101
+ Squealer::Database.instance.should_receive(:export)
102
+ export
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ def mock_mysql
110
+ require 'data_objects'
111
+
112
+ my = mock(DataObjects::Connection)
113
+ comm = mock(DataObjects::Command)
114
+ Squealer::Database.instance.should_receive(:export).at_least(:once).and_return(my)
115
+ my.should_receive(:create_command).at_least(:once).and_return(comm)
116
+ comm.should_receive(:execute_non_query).at_least(:once)
117
+ end
118
+
119
+ end