Use activerecord-import for bulk importing tracepoint records
[rails.git] / test / models / trace_test.rb
1 require "test_helper"
2 require "minitest/mock"
3
4 class TraceTest < ActiveSupport::TestCase
5   def teardown
6     File.unlink(*Dir.glob(File.join(Settings.gpx_trace_dir, "*.gpx")))
7     File.unlink(*Dir.glob(File.join(Settings.gpx_image_dir, "*.gif")))
8   end
9
10   def test_visible
11     public_trace_file = create(:trace)
12     create(:trace, :deleted)
13     check_query(Trace.visible, [public_trace_file])
14   end
15
16   def test_visible_to
17     first_user = create(:user)
18     second_user = create(:user)
19     third_user = create(:user)
20     fourth_user = create(:user)
21     public_trace_file = create(:trace, :visibility => "public", :user => first_user)
22     anon_trace_file = create(:trace, :visibility => "private", :user => second_user)
23     identifiable_trace_file = create(:trace, :visibility => "identifiable", :user => first_user)
24     pending_trace_file = create(:trace, :visibility => "public", :user => second_user, :inserted => false)
25     trackable_trace_file = create(:trace, :visibility => "trackable", :user => second_user)
26     _other_trace_file = create(:trace, :visibility => "private", :user => third_user)
27
28     check_query(Trace.visible_to(first_user), [
29                   public_trace_file, identifiable_trace_file, pending_trace_file
30                 ])
31     check_query(Trace.visible_to(second_user), [
32                   public_trace_file, anon_trace_file, trackable_trace_file,
33                   identifiable_trace_file, pending_trace_file
34                 ])
35     check_query(Trace.visible_to(fourth_user), [
36                   public_trace_file, identifiable_trace_file, pending_trace_file
37                 ])
38   end
39
40   def test_visible_to_all
41     public_trace_file = create(:trace, :visibility => "public")
42     _private_trace_file = create(:trace, :visibility => "private")
43     identifiable_trace_file = create(:trace, :visibility => "identifiable")
44     _trackable_trace_file = create(:trace, :visibility => "trackable")
45     deleted_trace_file = create(:trace, :deleted, :visibility => "public")
46     pending_trace_file = create(:trace, :visibility => "public", :inserted => false)
47
48     check_query(Trace.visible_to_all, [
49                   public_trace_file, identifiable_trace_file,
50                   deleted_trace_file, pending_trace_file
51                 ])
52   end
53
54   def test_tagged
55     london_trace_file = create(:trace) do |trace|
56       create(:tracetag, :trace => trace, :tag => "London")
57     end
58     birmingham_trace_file = create(:trace) do |trace|
59       create(:tracetag, :trace => trace, :tag => "Birmingham")
60     end
61     check_query(Trace.tagged("London"), [london_trace_file])
62     check_query(Trace.tagged("Birmingham"), [birmingham_trace_file])
63     check_query(Trace.tagged("Unknown"), [])
64   end
65
66   def test_validations
67     trace_valid({})
68     trace_valid({ :user_id => nil }, false)
69     trace_valid(:name => "a" * 255)
70     trace_valid({ :name => "a" * 256 }, false)
71     trace_valid({ :description => nil }, false)
72     trace_valid(:description => "a" * 255)
73     trace_valid({ :description => "a" * 256 }, false)
74     trace_valid(:visibility => "private")
75     trace_valid(:visibility => "public")
76     trace_valid(:visibility => "trackable")
77     trace_valid(:visibility => "identifiable")
78     trace_valid({ :visibility => "foo" }, false)
79   end
80
81   def test_tagstring
82     trace = build(:trace)
83     trace.tagstring = "foo bar baz"
84     assert trace.valid?
85     assert_equal 3, trace.tags.length
86     assert_equal "foo", trace.tags[0].tag
87     assert_equal "bar", trace.tags[1].tag
88     assert_equal "baz", trace.tags[2].tag
89     assert_equal "foo, bar, baz", trace.tagstring
90     trace.tagstring = "foo, bar baz ,qux"
91     assert trace.valid?
92     assert_equal 3, trace.tags.length
93     assert_equal "foo", trace.tags[0].tag
94     assert_equal "bar baz", trace.tags[1].tag
95     assert_equal "qux", trace.tags[2].tag
96     assert_equal "foo, bar baz, qux", trace.tagstring
97   end
98
99   def test_public?
100     assert_equal true, build(:trace, :visibility => "public").public?
101     assert_equal false, build(:trace, :visibility => "private").public?
102     assert_equal false, build(:trace, :visibility => "trackable").public?
103     assert_equal true, build(:trace, :visibility => "identifiable").public?
104     assert_equal true, build(:trace, :deleted, :visibility => "public").public?
105   end
106
107   def test_trackable?
108     assert_equal false, build(:trace, :visibility => "public").trackable?
109     assert_equal false, build(:trace, :visibility => "private").trackable?
110     assert_equal true, build(:trace, :visibility => "trackable").trackable?
111     assert_equal true, build(:trace, :visibility => "identifiable").trackable?
112     assert_equal false, build(:trace, :deleted, :visibility => "public").trackable?
113   end
114
115   def test_identifiable?
116     assert_equal false, build(:trace, :visibility => "public").identifiable?
117     assert_equal false, build(:trace, :visibility => "private").identifiable?
118     assert_equal false, build(:trace, :visibility => "trackable").identifiable?
119     assert_equal true, build(:trace, :visibility => "identifiable").identifiable?
120     assert_equal false, build(:trace, :deleted, :visibility => "public").identifiable?
121   end
122
123   def test_mime_type
124     # The ids refer to the .gpx fixtures in test/traces
125     check_mime_type("a", "application/gpx+xml")
126     check_mime_type("b", "application/gpx+xml")
127     check_mime_type("c", "application/x-bzip2")
128     check_mime_type("d", "application/x-gzip")
129     check_mime_type("f", "application/x-zip")
130     check_mime_type("g", "application/x-tar")
131     check_mime_type("h", "application/x-gzip")
132     check_mime_type("i", "application/x-bzip2")
133   end
134
135   def test_extension_name
136     # The ids refer to the .gpx fixtures in test/traces
137     check_extension_name("a", ".gpx")
138     check_extension_name("b", ".gpx")
139     check_extension_name("c", ".gpx.bz2")
140     check_extension_name("d", ".gpx.gz")
141     check_extension_name("f", ".zip")
142     check_extension_name("g", ".tar")
143     check_extension_name("h", ".tar.gz")
144     check_extension_name("i", ".tar.bz2")
145   end
146
147   def test_xml_file
148     check_xml_file("a", "848caa72f2f456d1bd6a0fdf228aa1b9")
149     check_xml_file("b", "66179ca44f1e93d8df62e2b88cbea732")
150     check_xml_file("c", "848caa72f2f456d1bd6a0fdf228aa1b9")
151     check_xml_file("d", "abd6675fdf3024a84fc0a1deac147c0d")
152     check_xml_file("f", "848caa72f2f456d1bd6a0fdf228aa1b9")
153     check_xml_file("g", "848caa72f2f456d1bd6a0fdf228aa1b9")
154     check_xml_file("h", "848caa72f2f456d1bd6a0fdf228aa1b9")
155     check_xml_file("i", "848caa72f2f456d1bd6a0fdf228aa1b9")
156   end
157
158   def test_large_picture
159     picture = File.read(Rails.root.join("test", "gpx", "fixtures", "a.gif"), :mode => "rb")
160
161     trace = Trace.create
162     trace.large_picture = picture
163     assert_equal "7c841749e084ee4a5d13f12cd3bef456", md5sum(File.new(trace.large_picture_name))
164     assert_equal picture, trace.large_picture
165
166     trace.destroy
167   end
168
169   def test_icon_picture
170     picture = File.read(Rails.root.join("test", "gpx", "fixtures", "a_icon.gif"), :mode => "rb")
171
172     trace = Trace.create
173     trace.icon_picture = picture
174     assert_equal "b47baf22ed0e85d77e808694fad0ee27", md5sum(File.new(trace.icon_picture_name))
175     assert_equal picture, trace.icon_picture
176
177     trace.destroy
178   end
179
180   # When testing the trace.import method, care needs to be taken regarding the icon
181   # fixture files, since the fixtures could be overwritten by newly generated files.
182   # We use FakeFS to temporarily protect the real fixture files from being overwritten.
183
184   def test_import_removes_previous_tracepoints
185     FakeFS do
186       FakeFS::FileSystem.clone(Rails.root.join("test", "gpx"))
187       trace = create(:trace, :fixture => "a")
188       # Tracepoints don't have a primary key, so we use a specific latitude to
189       # check for successful deletion
190       create(:tracepoint, :latitude => 54321, :trace => trace)
191       assert_equal 1, Tracepoint.where(:latitude => 54321).count
192
193       trace.import
194
195       assert_equal 0, Tracepoint.where(:latitude => 54321).count
196     end
197   end
198
199   def test_import_creates_tracepoints
200     FakeFS do
201       FakeFS::FileSystem.clone(Rails.root.join("test", "gpx"))
202       trace = create(:trace, :fixture => "a")
203       assert_equal 0, Tracepoint.where(:gpx_id => trace.id).count
204
205       trace.import
206
207       trace.reload
208       assert_equal 1, Tracepoint.where(:gpx_id => trace.id).count
209
210       # Check that the tile has been set prior to the bulk import
211       # i.e. that the callbacks have been run correctly
212       assert_equal 3221331576, Tracepoint.where(:gpx_id => trace.id).first.tile
213     end
214   end
215
216   def test_import_creates_icon
217     FakeFS do
218       FakeFS::FileSystem.clone(Rails.root.join("test", "gpx"))
219       trace = create(:trace, :fixture => "a")
220       icon_path = File.join(Settings.gpx_image_dir, "#{trace.id}_icon.gif")
221       FileUtils.rm(icon_path)
222       assert_equal false, File.exist?(icon_path)
223
224       trace.import
225
226       assert_equal true, File.exist?(icon_path)
227     end
228   end
229
230   def test_import_creates_large_picture
231     FakeFS do
232       FakeFS::FileSystem.clone(Rails.root.join("test", "gpx"))
233       trace = create(:trace, :fixture => "a")
234       large_picture_path = File.join(Settings.gpx_image_dir, "#{trace.id}.gif")
235       FileUtils.rm(large_picture_path)
236       assert_equal false, File.exist?(large_picture_path)
237
238       trace.import
239
240       assert_equal true, File.exist?(large_picture_path)
241     end
242   end
243
244   private
245
246   def check_query(query, traces)
247     traces = traces.map(&:id).sort
248     assert_equal traces, query.order(:id).ids
249   end
250
251   def check_mime_type(id, mime_type)
252     assert_equal mime_type, create(:trace, :fixture => id).mime_type
253   end
254
255   def check_extension_name(id, extension_name)
256     assert_equal extension_name, create(:trace, :fixture => id).extension_name
257   end
258
259   def check_xml_file(id, md5sum)
260     assert_equal md5sum, md5sum(create(:trace, :fixture => id).xml_file)
261   end
262
263   def trace_valid(attrs, result = true)
264     entry = build(:trace, attrs)
265     assert_equal result, entry.valid?, "Expected #{attrs.inspect} to be #{result}"
266   end
267
268   def md5sum(io)
269     io.each_with_object(Digest::MD5.new) { |l, d| d.update(l) }.hexdigest
270   end
271 end