Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve mocking framework for tests #871

Merged
merged 2 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ import Config
#

config :realtime_signs,
location_engine: Engine.Locations,
config_engine: Engine.Config,
headway_engine: Engine.ScheduledHeadways,
prediction_engine: Engine.Predictions,
alert_engine: Engine.Alerts,
last_trip_engine: Engine.LastTrip,
bridge_engine: Engine.ChelseaBridge,
route_engine: Engine.Routes,
bus_prediction_engine: Engine.BusPredictions,
sign_updater: PaEss.Updater,
http_client: HTTPoison,
posts_log_dir: "log/posts/",
time_zone: "America/New_York",
Expand Down
10 changes: 10 additions & 0 deletions config/test.exs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import Config

config :realtime_signs,
location_engine: Engine.Locations.Mock,
config_engine: Engine.Config.Mock,
headway_engine: Engine.ScheduledHeadways.Mock,
prediction_engine: Engine.Predictions.Mock,
alert_engine: Engine.Alerts.Mock,
last_trip_engine: Engine.LastTrip.Mock,
bridge_engine: Engine.ChelseaBridge.Mock,
route_engine: Engine.Routes.Mock,
bus_prediction_engine: Engine.BusPredictions.Mock,
sign_updater: PaEss.Updater.Mock,
http_client: Fake.HTTPoison,
trip_update_url: "https://fake_update/mbta-gtfs-s3/fake_trip_update.json",
sign_head_end_host: "signs.example.com",
Expand Down
7 changes: 3 additions & 4 deletions lib/engine/alerts.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
defmodule Engine.Alerts do
@behaviour Engine.AlertsAPI
use GenServer
require Logger
alias Engine.Alerts.Fetcher
Expand All @@ -25,7 +24,7 @@ defmodule Engine.Alerts do
GenServer.start_link(__MODULE__, opts, name: name)
end

@impl true
@callback max_stop_status([Fetcher.stop_id()], [Fetcher.route_id()]) :: Fetcher.stop_status()
def max_stop_status(
tables \\ %{stops_table: @stops_table, routes_table: @routes_table},
stop_ids,
Expand All @@ -51,15 +50,15 @@ defmodule Engine.Alerts do
end
end

@spec stop_status(:ets.tab(), Fetcher.stop_id()) :: Fetcher.stop_status()
@callback stop_status(Fetcher.stop_id()) :: Fetcher.stop_status()
def stop_status(ets_table_name \\ @stops_table, stop_id) do
case :ets.lookup(ets_table_name, stop_id) do
[{^stop_id, status}] -> status
_ -> :none
end
end

@spec route_status(:ets.tab(), Fetcher.route_id()) :: Fetcher.stop_status()
@callback route_status(Fetcher.route_id()) :: Fetcher.stop_status()
def route_status(ets_table_name \\ @routes_table, route_id) do
case :ets.lookup(ets_table_name, route_id) do
[{^route_id, status}] -> status
Expand Down
4 changes: 0 additions & 4 deletions lib/engine/alerts_api.ex

This file was deleted.

1 change: 1 addition & 0 deletions lib/engine/bus_predictions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Engine.BusPredictions do
use GenServer
require Logger

@callback predictions_for_stop(String.t()) :: [Predictions.BusPrediction.t()]
def predictions_for_stop(id) do
case :ets.lookup(:bus_predictions, id) do
[{^id, predictions}] -> predictions
Expand Down
1 change: 1 addition & 0 deletions lib/engine/chelsea_bridge.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ defmodule Engine.ChelseaBridge do
use GenServer
require Logger

@callback bridge_status() :: %{raised: boolean() | nil, estimate: DateTime.t() | nil}
def bridge_status() do
case :ets.lookup(:bridge_status, :value) do
[{:value, data}] -> data
Expand Down
11 changes: 5 additions & 6 deletions lib/engine/config.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ defmodule Engine.Config do
@moduledoc """
Manages the dynamic configurable pieces of the signs such as if they are on
"""
@behaviour Engine.ConfigAPI

use GenServer
require Logger
alias Engine.Config.Headway
Expand Down Expand Up @@ -31,29 +29,30 @@ defmodule Engine.Config do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end

@impl true
@callback sign_config(id :: String.t(), default :: Engine.Config.sign_config()) ::
Engine.Config.sign_config()
def sign_config(table \\ @table_signs, sign_id, default) do
case :ets.lookup(table, sign_id) do
[{^sign_id, config}] when not is_nil(config) -> config
_ -> default
end
end

@impl true
@callback headway_config(String.t(), DateTime.t()) :: Engine.Config.Headway.t() | nil
def headway_config(table_name \\ @table_headways, headway_group, current_time) do
time_period = Headway.current_time_period(current_time)
Headways.get_headway(table_name, {headway_group, time_period})
end

@impl true
@callback scu_migrated?(String.t()) :: boolean()
def scu_migrated?(table_name \\ @table_scus_migrated, scu_id) do
case :ets.lookup(table_name, scu_id) do
[{^scu_id, value}] -> value
_ -> false
end
end

@spec chelsea_bridge_config(:ets.tab()) :: :off | :auto
@callback chelsea_bridge_config() :: :off | :auto
def chelsea_bridge_config(table_name \\ @table_chelsea_bridge) do
case :ets.lookup(table_name, :status) do
[{_, "auto"}] -> :auto
Expand Down
6 changes: 0 additions & 6 deletions lib/engine/config_api.ex

This file was deleted.

5 changes: 2 additions & 3 deletions lib/engine/last_trip.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
defmodule Engine.LastTrip do
@behaviour Engine.LastTripAPI
use GenServer
require Logger

Expand All @@ -16,15 +15,15 @@ defmodule Engine.LastTrip do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end

@impl true
@callback get_recent_departures(String.t()) :: map()
def get_recent_departures(recent_departures_table \\ @recent_departures_table, stop_id) do
case :ets.lookup(recent_departures_table, stop_id) do
[{^stop_id, departures}] -> departures
_ -> []
end
end

@impl true
@callback is_last_trip?(String.t()) :: boolean()
def is_last_trip?(last_trips_table \\ @last_trips_table, trip_id) do
case :ets.lookup(last_trips_table, trip_id) do
[{^trip_id, _timestamp}] -> true
Expand Down
4 changes: 0 additions & 4 deletions lib/engine/last_trip_api.ex

This file was deleted.

6 changes: 2 additions & 4 deletions lib/engine/locations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ defmodule Engine.Locations do
Maintains an up-to-date internal state of the realtime locations of vehicles in the system. Fetches
from the GTFS-rt enhanced JSON file about once per second.
"""
@behaviour Engine.LocationsAPI

use GenServer
require Logger
alias Signs.Utilities.EtsUtils
Expand All @@ -22,7 +20,7 @@ defmodule Engine.Locations do
GenServer.start_link(__MODULE__, [], name: __MODULE__)
end

@impl true
@callback for_vehicle(String.t()) :: Locations.Location.t()
def for_vehicle(locations_table_id \\ @vehicle_locations_table, vehicle_id) do
case :ets.lookup(locations_table_id, vehicle_id) do
[{_, :none}] -> nil
Expand All @@ -31,7 +29,7 @@ defmodule Engine.Locations do
end
end

@impl true
@callback for_stop(String.t()) :: [Locations.Location.t()]
def for_stop(stop_id) do
case :ets.lookup(@stop_locations_table, stop_id) do
[{^stop_id, locations}] -> locations
Expand Down
4 changes: 0 additions & 4 deletions lib/engine/locations_api.ex

This file was deleted.

6 changes: 2 additions & 4 deletions lib/engine/predictions.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ defmodule Engine.Predictions do
Offers a `for_stop/1` public interface to get a list of Predictions.Prediction's
for a given GTFS stop.
"""
@behaviour Engine.PredictionsAPI

use GenServer
require Logger
alias Signs.Utilities.EtsUtils
Expand All @@ -23,15 +21,15 @@ defmodule Engine.Predictions do
end

@doc "The upcoming predicted times a vehicle will be at this stop"
@impl true
@callback for_stop(String.t(), 0 | 1) :: [Predictions.Prediction.t()]
def for_stop(predictions_table_id \\ :trip_updates, gtfs_stop_id, direction_id) do
case :ets.lookup(predictions_table_id, {gtfs_stop_id, direction_id}) do
[{{^gtfs_stop_id, ^direction_id}, predictions}] -> predictions
_ -> []
end
end

@impl true
@callback revenue_vehicles() :: MapSet.t()
def revenue_vehicles() do
case :ets.lookup(:revenue_vehicles, :all) do
[{:all, data}] -> data
Expand Down
4 changes: 0 additions & 4 deletions lib/engine/predictions_api.ex

This file was deleted.

2 changes: 1 addition & 1 deletion lib/engine/routes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Engine.Routes do
use GenServer
require Logger

@spec route_destination(String.t(), 0 | 1) :: String.t() | nil
@callback route_destination(String.t(), 0 | 1) :: String.t() | nil
def route_destination(route_id, direction_id) do
case :ets.lookup(:route_destinations, {route_id, direction_id}) do
[{{^route_id, ^direction_id}, destination}] -> destination
Expand Down
5 changes: 2 additions & 3 deletions lib/engine/scheduled_headways.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ defmodule Engine.ScheduledHeadways do
Initially we will quickly update any newly registered stop so that we have something to show,
then over time we will update every stop once every hour to make sure we stay up to date.
"""
@behaviour Engine.ScheduledHeadwaysAPI
use GenServer
require Logger
require Signs.Utilities.SignsConfig
Expand Down Expand Up @@ -79,7 +78,7 @@ defmodule Engine.ScheduledHeadways do
:ets.select(table_name, pattern)
end

@impl true
@callback get_first_scheduled_departure([binary]) :: nil | DateTime.t()
def get_first_scheduled_departure(stop_ids) do
get_first_last_departures(stop_ids)
|> Enum.map(&elem(&1, 0))
Expand All @@ -89,7 +88,7 @@ defmodule Engine.ScheduledHeadways do
@doc "Checks if the given time is after the first scheduled stop and before the last.
A buffer of minutes (positive) is subtracted from the first time. so that headways are
shown for a short time before the first train."
@impl true
@callback display_headways?([String.t()], DateTime.t(), Engine.Config.Headway.t()) :: boolean()
def display_headways?(
table \\ :scheduled_headways_first_last_departures,
stop_ids,
Expand Down
4 changes: 0 additions & 4 deletions lib/engine/scheduled_headways_api.ex

This file was deleted.

16 changes: 5 additions & 11 deletions lib/headway_analysis/server.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ defmodule HeadwayAnalysis.Server do
:sign_id,
:headway_group,
:stop_ids,
:vehicles_present,
:prediction_engine,
:config_engine,
:location_engine
:vehicles_present
]
defstruct @enforce_keys

Expand All @@ -31,10 +28,7 @@ defmodule HeadwayAnalysis.Server do
sign_id: config["id"],
headway_group: config["source_config"]["headway_group"],
stop_ids: Enum.map(config["source_config"]["sources"], & &1["stop_id"]),
vehicles_present: MapSet.new(),
prediction_engine: Engine.Predictions,
config_engine: Engine.Config,
location_engine: Engine.Locations
vehicles_present: MapSet.new()
}}
end

Expand All @@ -46,16 +40,16 @@ defmodule HeadwayAnalysis.Server do
DateTime.utc_now() |> DateTime.shift_zone!(Application.get_env(:realtime_signs, :time_zone))

{headway_low, headway_high} =
case state.config_engine.headway_config(state.headway_group, current_time) do
case RealtimeSigns.config_engine().headway_config(state.headway_group, current_time) do
%Engine.Config.Headway{range_low: low, range_high: high} -> {low, high}
nil -> {nil, nil}
end

revenue_vehicles = state.prediction_engine.revenue_vehicles()
revenue_vehicles = RealtimeSigns.prediction_engine().revenue_vehicles()

new_vehicles_present =
for stop_id <- state.stop_ids,
location <- state.location_engine.for_stop(stop_id),
location <- RealtimeSigns.location_engine().for_stop(stop_id),
location.status == :stopped_at,
into: MapSet.new() do
location.vehicle_id
Expand Down
28 changes: 17 additions & 11 deletions lib/pa_ess/updater.ex
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
defmodule PaEss.Updater do
@behaviour PaEss.UpdaterAPI

require Logger

@impl true
@callback set_background_message(
Signs.Realtime.t() | Signs.Bus.t(),
Content.Message.value(),
Content.Message.value()
) :: :ok
def set_background_message(
%{
id: id,
scu_id: scu_id,
pa_ess_loc: pa_ess_loc,
text_zone: text_zone,
default_mode: default_mode,
config_engine: config_engine
default_mode: default_mode
},
top,
bottom
) do
log_config =
case config_engine.sign_config(id, default_mode) do
case RealtimeSigns.config_engine().sign_config(id, default_mode) do
mode when is_atom(mode) -> mode
mode when is_tuple(mode) -> elem(mode, 0)
_ -> nil
end

visual = zip_pages(top, bottom) |> format_pages()
tag = create_tag()
scu_migrated? = config_engine.scu_migrated?(scu_id)
scu_migrated? = RealtimeSigns.config_engine().scu_migrated?(scu_id)

log_meta = [
sign_id: id,
Expand All @@ -51,21 +52,26 @@ defmodule PaEss.Updater do
end
end

@impl true
@callback play_message(
Signs.Realtime.t() | Signs.Bus.t(),
[Content.Audio.value()],
[Content.Audio.tts_value()],
[keyword()]
) ::
:ok
def play_message(
%{
id: id,
scu_id: scu_id,
pa_ess_loc: pa_ess_loc,
audio_zones: audio_zones,
config_engine: config_engine
audio_zones: audio_zones
},
audios,
tts_audios,
log_metas
) do
tags = Enum.map(audios, fn _ -> create_tag() end)
scu_migrated? = config_engine.scu_migrated?(scu_id)
scu_migrated? = RealtimeSigns.config_engine().scu_migrated?(scu_id)

log_metas =
Enum.zip([tts_audios, tags, log_metas])
Expand Down
Loading
Loading