Skip to content

Commit 6561b3b

Browse files
authored
NeTEx -> GeoJSON : Couverture de tests (#5474)
1 parent 8e83542 commit 6561b3b

5 files changed

Lines changed: 271 additions & 88 deletions

File tree

apps/transport/lib/netex/archive_parser.ex

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -201,21 +201,25 @@ defmodule Transport.NeTEx.ArchiveParser do
201201
end
202202

203203
defp read_all(zip_file_name, reader) do
204-
with_zip_file_handle(zip_file_name, fn unzip ->
205-
unzip
206-
|> Unzip.list_entries()
207-
|> Enum.map(fn metadata ->
208-
Logger.debug("Processing #{metadata.file_name}")
209-
210-
{
211-
metadata.file_name,
212-
reader.(unzip, metadata.file_name)
213-
}
214-
end)
215-
end)
216-
end
217-
218-
def with_zip_file_handle(zip_file_name, cb) do
204+
with_zip_file_handle(
205+
zip_file_name,
206+
fn unzip ->
207+
unzip
208+
|> Unzip.list_entries()
209+
|> Enum.map(fn metadata ->
210+
Logger.debug("Processing #{metadata.file_name}")
211+
212+
{
213+
metadata.file_name,
214+
reader.(unzip, metadata.file_name)
215+
}
216+
end)
217+
end,
218+
fn _error -> [] end
219+
)
220+
end
221+
222+
def with_zip_file_handle(zip_file_name, cb, on_error) do
219223
zip_file = Unzip.LocalFile.open(zip_file_name)
220224

221225
try do
@@ -225,7 +229,7 @@ defmodule Transport.NeTEx.ArchiveParser do
225229

226230
{:error, message} ->
227231
Logger.error("Error while reading #{zip_file_name}: #{message}")
228-
[]
232+
on_error.(message)
229233
end
230234
after
231235
Unzip.LocalFile.close(zip_file)

apps/transport/lib/netex/to_geojson/to_geojson.ex

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,20 @@ defmodule Transport.NeTEx.ToGeoJSON do
5050
def convert_archive(zip_path, opts \\ []) do
5151
types = Keyword.get(opts, :types, @all_types)
5252

53-
Transport.NeTEx.ArchiveParser.with_zip_file_handle(zip_path, fn unzip ->
54-
features =
55-
unzip
56-
|> Unzip.list_entries()
57-
|> Enum.flat_map(fn metadata ->
58-
extract_features_from_entry(unzip, metadata.file_name, types)
59-
end)
60-
61-
{:ok, GeoJSONBuilder.feature_collection(features)}
62-
end)
63-
rescue
64-
e -> {:error, Exception.message(e)}
53+
Transport.NeTEx.ArchiveParser.with_zip_file_handle(
54+
zip_path,
55+
fn unzip ->
56+
features =
57+
unzip
58+
|> Unzip.list_entries()
59+
|> Enum.flat_map(fn metadata ->
60+
extract_features_from_entry(unzip, metadata.file_name, types)
61+
end)
62+
63+
{:ok, GeoJSONBuilder.feature_collection(features)}
64+
end,
65+
fn e -> {:error, e} end
66+
)
6567
end
6668

6769
@doc """

apps/transport/test/netex/to_geojson/to_geojson_test.exs

Lines changed: 50 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,6 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
33

44
alias Transport.NeTEx.ToGeoJSON
55

6-
defmodule ZipCreator do
7-
@spec create!(String.t(), [{String.t(), binary()}]) :: no_return()
8-
def create!(zip_filename, file_data) do
9-
{:ok, ^zip_filename} =
10-
:zip.create(
11-
zip_filename,
12-
file_data
13-
|> Enum.map(fn {name, content} -> {name |> to_charlist(), content} end)
14-
)
15-
end
16-
end
17-
186
describe "convert_xml/1" do
197
test "converts StopPlaces to Point features" do
208
xml = """
@@ -305,19 +293,16 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
305293
</root>
306294
"""
307295

308-
tmp_file = System.tmp_dir!() |> Path.join("netex-geojson-#{Ecto.UUID.generate()}.zip")
309-
ZipCreator.create!(tmp_file, [{"stops.xml", xml1}, {"quays.xml", xml2}])
296+
ZipCreator.with_tmp_zip([{"stops.xml", xml1}, {"quays.xml", xml2}], fn tmp_file ->
297+
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file)
310298

311-
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file)
299+
assert geojson["type"] == "FeatureCollection"
300+
assert length(geojson["features"]) == 2
312301

313-
assert geojson["type"] == "FeatureCollection"
314-
assert length(geojson["features"]) == 2
315-
316-
ids = Enum.map(geojson["features"], & &1["id"])
317-
assert "stop_1" in ids
318-
assert "quay_1" in ids
319-
320-
File.rm!(tmp_file)
302+
ids = Enum.map(geojson["features"], & &1["id"])
303+
assert "stop_1" in ids
304+
assert "quay_1" in ids
305+
end)
321306
end
322307

323308
test "filters by types option" do
@@ -344,15 +329,12 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
344329
</root>
345330
"""
346331

347-
tmp_file = System.tmp_dir!() |> Path.join("netex-geojson-#{Ecto.UUID.generate()}.zip")
348-
ZipCreator.create!(tmp_file, [{"data.xml", xml}])
349-
350-
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file, types: [:quays])
351-
352-
assert length(geojson["features"]) == 1
353-
assert hd(geojson["features"])["id"] == "quay_1"
332+
ZipCreator.with_tmp_zip([{"data.xml", xml}], fn tmp_file ->
333+
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file, types: [:quays])
354334

355-
File.rm!(tmp_file)
335+
assert length(geojson["features"]) == 1
336+
assert hd(geojson["features"])["id"] == "quay_1"
337+
end)
356338
end
357339

358340
test "skips non-XML files" do
@@ -370,14 +352,11 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
370352
</root>
371353
"""
372354

373-
tmp_file = System.tmp_dir!() |> Path.join("netex-geojson-#{Ecto.UUID.generate()}.zip")
374-
ZipCreator.create!(tmp_file, [{"data.xml", xml}, {"readme.txt", "Some text"}])
375-
376-
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file)
377-
378-
assert length(geojson["features"]) == 1
355+
ZipCreator.with_tmp_zip([{"data.xml", xml}, {"readme.txt", "Some text"}], fn tmp_file ->
356+
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file)
379357

380-
File.rm!(tmp_file)
358+
assert length(geojson["features"]) == 1
359+
end)
381360
end
382361

383362
test "skips directories" do
@@ -395,15 +374,12 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
395374
</root>
396375
"""
397376

398-
tmp_file = System.tmp_dir!() |> Path.join("netex-geojson-#{Ecto.UUID.generate()}.zip")
399-
ZipCreator.create!(tmp_file, [{"subdir/data.xml", xml}])
377+
ZipCreator.with_tmp_zip([{"subdir/data.xml", xml}], fn tmp_file ->
378+
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file)
400379

401-
assert {:ok, geojson} = ToGeoJSON.convert_archive(tmp_file)
402-
403-
# Should still find the XML in the subdirectory
404-
assert length(geojson["features"]) == 1
405-
406-
File.rm!(tmp_file)
380+
# Should still find the XML in the subdirectory
381+
assert length(geojson["features"]) == 1
382+
end)
407383
end
408384
end
409385

@@ -423,15 +399,12 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
423399
</root>
424400
"""
425401

426-
tmp_file = System.tmp_dir!() |> Path.join("netex-geojson-#{Ecto.UUID.generate()}.zip")
427-
ZipCreator.create!(tmp_file, [{"data.xml", xml}])
428-
429-
assert {:ok, geojson} = Transport.NeTEx.ArchiveParser.to_geojson(tmp_file)
402+
ZipCreator.with_tmp_zip([{"data.xml", xml}], fn tmp_file ->
403+
assert {:ok, geojson} = Transport.NeTEx.ArchiveParser.to_geojson(tmp_file)
430404

431-
assert geojson["type"] == "FeatureCollection"
432-
assert length(geojson["features"]) == 1
433-
434-
File.rm!(tmp_file)
405+
assert geojson["type"] == "FeatureCollection"
406+
assert length(geojson["features"]) == 1
407+
end)
435408
end
436409

437410
test "accepts types option" do
@@ -458,15 +431,32 @@ defmodule Transport.NeTEx.ToGeoJSONTest do
458431
</root>
459432
"""
460433

461-
tmp_file = System.tmp_dir!() |> Path.join("netex-geojson-#{Ecto.UUID.generate()}.zip")
462-
ZipCreator.create!(tmp_file, [{"data.xml", xml}])
434+
ZipCreator.with_tmp_zip([{"data.xml", xml}], fn tmp_file ->
435+
assert {:ok, geojson} = Transport.NeTEx.ArchiveParser.to_geojson(tmp_file, types: [:stop_places])
436+
437+
assert length(geojson["features"]) == 1
438+
assert hd(geojson["features"])["id"] == "stop_1"
439+
end)
440+
end
463441

464-
assert {:ok, geojson} = Transport.NeTEx.ArchiveParser.to_geojson(tmp_file, types: [:stop_places])
442+
test "empty archive" do
443+
ZipCreator.with_tmp_zip([], fn tmp_file ->
444+
assert {:ok, geojson} = Transport.NeTEx.ArchiveParser.to_geojson(tmp_file, types: [:stop_places])
465445

466-
assert length(geojson["features"]) == 1
467-
assert hd(geojson["features"])["id"] == "stop_1"
446+
assert geojson == %{"features" => [], "type" => "FeatureCollection"}
447+
end)
448+
end
449+
450+
test "bad NeTEx" do
451+
xml = """
452+
not an XML
453+
"""
454+
455+
ZipCreator.with_tmp_zip([{"data.xml", xml}], fn tmp_file ->
456+
assert {:ok, geojson} = Transport.NeTEx.ArchiveParser.to_geojson(tmp_file, types: [:stop_places])
468457

469-
File.rm!(tmp_file)
458+
assert geojson == %{"features" => [], "type" => "FeatureCollection"}
459+
end)
470460
end
471461
end
472462
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
defmodule Transport.Jobs.NeTExToGeoJSONConverterJobTest do
2+
use ExUnit.Case, async: true
3+
use Oban.Testing, repo: DB.Repo
4+
import DB.Factory
5+
import Mox
6+
alias Transport.Jobs.NeTExToGeoJSONConverterJob
7+
8+
setup do
9+
Ecto.Adapters.SQL.Sandbox.checkout(DB.Repo)
10+
end
11+
12+
setup :verify_on_exit!
13+
14+
test "NeTEx to GeoJSON jobs are enqueued" do
15+
%{id: resource_history_id} =
16+
insert(:resource_history,
17+
datagouv_id: "1",
18+
payload: %{"format" => "NeTEx", "uuid" => Ecto.UUID.generate()}
19+
)
20+
21+
insert(:resource_history,
22+
datagouv_id: "2",
23+
payload: %{"format" => "GTFS", "uuid" => Ecto.UUID.generate()}
24+
)
25+
26+
insert(:resource_history, datagouv_id: "3", payload: %{})
27+
28+
# Ignored because it previously had a fatal conversion error
29+
insert(:resource_history,
30+
datagouv_id: "4",
31+
payload: %{"format" => "NeTEx", "uuid" => Ecto.UUID.generate(), "conversion_GeoJSON_fatal_error" => true}
32+
)
33+
34+
# This resource_history should not get enqueued for conversion,
35+
# as a matching data_conversion already exists
36+
insert(:resource_history,
37+
datagouv_id: "4",
38+
payload: %{"format" => "NeTEx", uuid: uuid = Ecto.UUID.generate()}
39+
)
40+
41+
insert(:data_conversion,
42+
convert_from: :NeTEx,
43+
convert_to: :GeoJSON,
44+
converter: DB.DataConversion.converter_to_use(:NeTEx, :GeoJSON),
45+
resource_history_uuid: uuid,
46+
payload: %{}
47+
)
48+
49+
assert :ok = perform_job(NeTExToGeoJSONConverterJob, %{})
50+
51+
assert [%Oban.Job{args: %{"resource_history_id" => ^resource_history_id}}] =
52+
all_enqueued()
53+
end
54+
end

0 commit comments

Comments
 (0)