nsync 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,261 @@
1
+ require File.join(File.dirname(__FILE__), "helper")
2
+
3
+ class NsyncProducerTest < Test::Unit::TestCase
4
+ def setup
5
+ #Grit.debug = true
6
+ Nsync.reset_config
7
+ @lock_file = "/private/tmp/nsync_test_#{Process.pid}.lock"
8
+ FileUtils.rm @lock_file, :force => true
9
+ Nsync.config.lock_file = @lock_file
10
+ end
11
+
12
+ context "Initializing Producer" do
13
+ context "when the repo already exists" do
14
+ setup do
15
+ @repo = TestRepo.new
16
+
17
+ Nsync.config.repo_path = @repo.repo_path
18
+ end
19
+
20
+ should "not try to reinitialize it" do
21
+ Grit::Git.any_instance.expects(:init).never
22
+ @producer = Nsync::Producer.new
23
+ end
24
+ end
25
+
26
+ context "when the repo does not exist" do
27
+ setup do
28
+ @repo_path = TestRepo.repo_path
29
+ Nsync.config.repo_path = @repo_path
30
+ FileUtils.rm_rf @repo_path
31
+ end
32
+
33
+ should "initialize it and make a base commit" do
34
+ Grit::Repo.expects(:init).with(@repo_path).once
35
+ Nsync::Producer.any_instance.expects(:write_file).with(".gitignore", "").once
36
+ Nsync::Producer.any_instance.expects(:commit).returns(true).once
37
+ Nsync::Producer.new
38
+ end
39
+
40
+ should "initialize the repo into a working state" do
41
+ @producer = Nsync::Producer.new
42
+ assert_equal "Initial Commit", @producer.repo.head.commit.message
43
+ assert File.exists?(File.join(@repo_path, ".gitignore"))
44
+ end
45
+ end
46
+ end
47
+
48
+ context "Consumer methods that are probably not what you want" do
49
+ setup do
50
+ @repo = TestRepo.new
51
+
52
+ Nsync.config.repo_path = @repo.repo_path
53
+ @producer = Nsync::Producer.new
54
+ end
55
+
56
+ should "be protected" do
57
+ assert_equal [], @producer.public_methods & ["update", "apply_changes"]
58
+ end
59
+ end
60
+
61
+
62
+ context "Writing a file" do
63
+ setup do
64
+ @repo = TestRepo.new
65
+
66
+ Nsync.config.repo_path = @repo.repo_path
67
+ @producer = Nsync::Producer.new
68
+ end
69
+
70
+ context "when creating a file" do
71
+ setup do
72
+ @file = "foo/1.json"
73
+ @hash = {"id" => 1, "val" => "Shazam"}
74
+ end
75
+
76
+ should "write the file to disk, add it to the index, but not commit" do
77
+ @producer.repo.expects(:add).with(File.join(@repo.repo_path, @file)).once
78
+ @producer.expects(:commit).never
79
+ @producer.repo.expects(:commit_all).never
80
+ @producer.write_file(@file, @hash)
81
+
82
+ assert_equal JSON.load(File.read(File.join(@repo.repo_path, @file))), @hash
83
+ end
84
+ end
85
+
86
+ context "when modifying a file" do
87
+ setup do
88
+ @file = "foo/1.json"
89
+ @hash = {"id" => 1, "val" => "Shazam"}
90
+ @producer.write_file(@file, @hash)
91
+ end
92
+
93
+ should "behave just like a create" do
94
+ new_hash = {"id" => 1, "val" => "Kaboom"}
95
+ @producer.repo.expects(:add).with(File.join(@repo.repo_path, @file)).once
96
+ @producer.expects(:commit).never
97
+ @producer.write_file(@file, new_hash)
98
+
99
+ assert_equal JSON.load(File.read(File.join(@repo.repo_path, @file))), new_hash
100
+ end
101
+
102
+ context "but then removing it" do
103
+ setup do
104
+ @producer.remove_file(@file)
105
+ end
106
+
107
+ should "just be gone" do
108
+ assert !File.exists?(File.join(@repo.repo_path, @file))
109
+ end
110
+ end
111
+ end
112
+ end
113
+
114
+ context "Committing changes" do
115
+ setup do
116
+ @repo = TestRepo.new
117
+
118
+ Nsync.config.repo_path = @repo.repo_path
119
+ @producer = Nsync::Producer.new
120
+ end
121
+
122
+ should "commit all changes as well as push" do
123
+ @msg = "Test Update"
124
+ @producer.repo.expects(:commit_all).with(@msg).once
125
+ @producer.expects(:push).once
126
+ @producer.commit(@msg)
127
+ end
128
+ end
129
+
130
+ context "Pushing changes" do
131
+ setup do
132
+ @repo = TestRepo.new
133
+
134
+ Nsync.config.repo_path = @repo.repo_path
135
+ @producer = Nsync::Producer.new
136
+ end
137
+
138
+ context "when there is a remote push url" do
139
+ setup do
140
+ @push_url = "/tmp/foo/bar"
141
+ Nsync.config.repo_push_url = @push_url
142
+ end
143
+
144
+ should "push changes to that" do
145
+ @producer.repo.git.expects(:push).with({}, @push_url, "+master").once
146
+ @producer.push
147
+ end
148
+ end
149
+
150
+ context "when there is no remote push url" do
151
+ should "not try to push" do
152
+ @producer.repo.git.expects(:push).never
153
+ @producer.push
154
+ end
155
+ end
156
+ end
157
+
158
+ context "Because a producer is a consumer that consumes itself" do
159
+ setup do
160
+ @repo = TestRepo.new
161
+
162
+ Nsync.config.repo_path = @repo.repo_path
163
+ @producer = Nsync::Producer.new
164
+ end
165
+
166
+ context "the class mapping" do
167
+ setup do
168
+ Nsync.config.map_class "NsyncTestBar", "NsyncTestFoo"
169
+ end
170
+
171
+ context "when unset for a class" do
172
+ should "return the producer class" do
173
+ assert_equal [NsyncTestFoo],
174
+ @producer.send(:consumer_classes_and_id_from_path, "nsync_test_foo/1.json")[0]
175
+ end
176
+ end
177
+
178
+ context "when set for a class" do
179
+ should "return a consumer class normally" do
180
+ assert_equal [NsyncTestFoo],
181
+ @producer.send(:consumer_classes_and_id_from_path, "nsync_test_bar/1.json")[0]
182
+ end
183
+ end
184
+ end
185
+
186
+ context "rollback behaves quite differently" do
187
+ setup do
188
+ Nsync.config.version_manager = stub(:version => "bad_rev",
189
+ :previous_version => "good_rev")
190
+ end
191
+
192
+ should "reset from bad to good, apply changes between bad and good, and push" do
193
+ @producer.repo.git.expects(:reset).never
194
+ @producer.repo.git.expects(:reset).with({:hard => true}, "good_rev").once
195
+ @producer.expects(:apply_changes).with("bad_rev", "good_rev").once
196
+ @producer.expects(:push).once
197
+ @producer.rollback
198
+ end
199
+ end
200
+ end
201
+
202
+ context "basic flow" do
203
+ setup do
204
+ @repo_path = TestRepo.repo_path
205
+ @repo_push_url = TestRepo.bare_consumer_repo_path
206
+ FileUtils.rm_rf @repo_path
207
+ FileUtils.rm_rf @repo_push_url
208
+
209
+ @remote_repo = Grit::Repo.init_bare(@repo_push_url)
210
+ Nsync.config.repo_path = @repo_path
211
+ Nsync.config.repo_push_url = @repo_push_url
212
+ Nsync.config.version_manager = Nsync::GitVersionManager.new
213
+
214
+ @producer = Nsync::Producer.new
215
+ @repo = @producer.repo
216
+ end
217
+
218
+ should "work" do
219
+ @producer.write_file("nsync_test_foo/1.json", {:id => 1, :val => "Party"})
220
+ @producer.write_file("nsync_test_bar/2.json", {:id => 2, :val => "Study"})
221
+ assert_equal 1, @repo.commits.size
222
+ assert_equal 1, @remote_repo.commits.size
223
+ assert File.exists?(File.join(@repo_path, "nsync_test_foo/1.json"))
224
+ assert File.exists?(File.join(@repo_path, "nsync_test_bar/2.json"))
225
+ @producer.commit("Added some files")
226
+
227
+ assert_equal 2, @repo.commits.size
228
+ assert_equal 2, @remote_repo.commits.size
229
+
230
+ @producer.write_file("nsync_test_foo/2.json", {:id => 2, :val => "Rock"})
231
+ assert File.exists?(File.join(@repo_path, "nsync_test_foo/2.json"))
232
+ @producer.commit("And another")
233
+
234
+ assert_equal 3, @repo.commits.size
235
+ assert_equal 3, @remote_repo.commits.size
236
+
237
+ @producer.remove_file("nsync_test_bar/2.json")
238
+ assert !File.exists?(File.join(@repo_path, "nsync_test_bar/2.json"))
239
+ @producer.commit("Remove the no-fun brigade")
240
+
241
+ assert_equal 4, @repo.commits.size
242
+ assert_equal 4, @remote_repo.commits.size
243
+
244
+ NsyncTestBar.expects(:nsync_find).with('2').returns([]).once
245
+ NsyncTestBar.expects(:nsync_add_data).once
246
+
247
+ @producer.rollback
248
+
249
+ assert File.exists?(File.join(@repo_path, "nsync_test_bar/2.json"))
250
+ assert_equal 3, @repo.commits.size
251
+ assert_equal 3, @remote_repo.commits.size
252
+
253
+ @producer.write_file("nsync_test_bar/5.json", {:id => 5, :val => "No Fun"})
254
+ assert File.exists?(File.join(@repo_path, "nsync_test_bar/5.json"))
255
+ @producer.commit("Life goes on")
256
+
257
+ assert_equal 4, @repo.commits.size
258
+ assert_equal 4, @remote_repo.commits.size
259
+ end
260
+ end
261
+ end
data/test/repo.rb ADDED
@@ -0,0 +1,64 @@
1
+ class TestRepo
2
+ attr_accessor :repo
3
+
4
+ def initialize(opts={})
5
+ FileUtils.rm_rf(repo_path)
6
+ self.repo = Grit::Repo.init(repo_path)
7
+ add_file(".gitignore", "")
8
+ commit("Initial Commit")
9
+ end
10
+
11
+ def cd
12
+ old_pwd = FileUtils.pwd
13
+ begin
14
+ FileUtils.cd repo_path
15
+ yield
16
+ ensure
17
+ FileUtils.cd old_pwd
18
+ end
19
+ end
20
+
21
+ def repo_path
22
+ self.class.repo_path
23
+ end
24
+
25
+ def self.repo_path
26
+ "/private/tmp/nsync_test_repo_#{Process.pid}"
27
+ end
28
+
29
+ def bare_consumer_repo_path
30
+ self.class.bare_consumer_repo_path
31
+ end
32
+
33
+ def self.bare_consumer_repo_path
34
+ "#{repo_path}_consumer.git"
35
+ end
36
+
37
+ def self.repo_push_path
38
+ "#{repo_path}_producer_push.git"
39
+ end
40
+
41
+ def add_file(filename, content)
42
+ cd do
43
+ dir = File.dirname(filename)
44
+ if ![".", "/"].include?(dir) && !File.exists?(dir)
45
+ FileUtils.mkdir_p(File.join(repo_path, dir))
46
+ end
47
+ File.open(File.join(repo_path, filename), "w") do |f|
48
+ f.write((content.is_a?(Hash))? content.to_json : content)
49
+ end
50
+ repo.add(File.join(repo_path, filename))
51
+ end
52
+ end
53
+
54
+ def remove_file(filename)
55
+ FileUtils.rm File.join(repo_path, filename)
56
+ end
57
+
58
+ def commit(message)
59
+ cd do
60
+ repo.commit_all(message)
61
+ end
62
+ end
63
+
64
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: nsync
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Ben Hughes
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-12-06 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: json
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: activesupport
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 2
41
+ - 3
42
+ - 5
43
+ version: 2.3.5
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: schleyfox-grit
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 2
55
+ - 3
56
+ - 0
57
+ - 1
58
+ version: 2.3.0.1
59
+ type: :runtime
60
+ version_requirements: *id003
61
+ - !ruby/object:Gem::Dependency
62
+ name: schleyfox-lockfile
63
+ prerelease: false
64
+ requirement: &id004 !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 1
70
+ - 0
71
+ - 0
72
+ version: 1.0.0
73
+ type: :runtime
74
+ version_requirements: *id004
75
+ - !ruby/object:Gem::Dependency
76
+ name: shoulda
77
+ prerelease: false
78
+ requirement: &id005 !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ segments:
83
+ - 0
84
+ version: "0"
85
+ type: :development
86
+ version_requirements: *id005
87
+ - !ruby/object:Gem::Dependency
88
+ name: mocha
89
+ prerelease: false
90
+ requirement: &id006 !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ type: :development
98
+ version_requirements: *id006
99
+ description: |-
100
+ Nsync is designed to allow you to have a separate data
101
+ processing app with its own data processing optimized database and a consumer
102
+ app with its own database, while keeping the data as in sync as you want it.
103
+ email: ben@pixelmachine.org
104
+ executables: []
105
+
106
+ extensions: []
107
+
108
+ extra_rdoc_files:
109
+ - LICENSE
110
+ - README.md
111
+ files:
112
+ - LICENSE
113
+ - README.md
114
+ - Rakefile
115
+ - VERSION
116
+ - jeweler_monkey_patch.rb
117
+ - lib/nsync.rb
118
+ - lib/nsync/active_record/consumer/methods.rb
119
+ - lib/nsync/active_record/methods.rb
120
+ - lib/nsync/active_record/producer/methods.rb
121
+ - lib/nsync/class_methods.rb
122
+ - lib/nsync/config.rb
123
+ - lib/nsync/consumer.rb
124
+ - lib/nsync/git_version_manager.rb
125
+ - lib/nsync/producer.rb
126
+ - lib/nsync/producer/methods.rb
127
+ - nsync.gemspec
128
+ has_rdoc: true
129
+ homepage: http://github.com/schleyfox/nsync
130
+ licenses: []
131
+
132
+ post_install_message:
133
+ rdoc_options: []
134
+
135
+ require_paths:
136
+ - lib
137
+ required_ruby_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ segments:
149
+ - 0
150
+ version: "0"
151
+ requirements: []
152
+
153
+ rubyforge_project:
154
+ rubygems_version: 1.3.6
155
+ signing_key:
156
+ specification_version: 3
157
+ summary: Keep your data processors and apps in sync
158
+ test_files:
159
+ - test/active_record_test.rb
160
+ - test/classes.rb
161
+ - test/helper.rb
162
+ - test/nsync_config_test.rb
163
+ - test/nsync_consumer_test.rb
164
+ - test/nsync_producer_test.rb
165
+ - test/repo.rb