Add some tests

pull/375/head
Connor Rigby 2017-12-05 10:16:48 -08:00
parent 54f777edec
commit 34ef41632f
19 changed files with 260 additions and 20 deletions

View File

@ -17,7 +17,9 @@ config :farmbot, :init, [
]
# Transports.
config :farmbot, :transport, []
config :farmbot, :transport, [
Farmbot.BotState.Transport.Test
]
# Configure Farmbot Behaviours.
# config :farmbot, :behaviour,

View File

@ -239,7 +239,6 @@ defmodule Farmbot.BotState do
end
def handle_events(events, _from, state) do
# Logger.busy 3, "begin handle bot state events"
state = do_handle(events, state)
# Logger.success 3, "Finish handle bot state events"
{:noreply, [state], state}

View File

@ -37,6 +37,10 @@ defmodule Farmbot.CeleryScript.AST do
end
end
def encode(thing) do
{:error, "#{inspect thing} is not an AST node for encoding."}
end
@doc "Encode a list of asts."
def encode_body(body, acc \\ [])

View File

@ -6,7 +6,7 @@ defmodule Farmbot.CeleryScript.AST.Node.MoveRelative do
def execute(%{x: x, y: y, z: z, speed: speed}, _, env) do
env = mutate_env(env)
%{location_data: %{position: %{x: cur_x, y: cur_y, z: cur_z}}} = Farmbot.BotState.force_state_push
%{x: cur_x, y: cur_y, z: cur_z} = Farmbot.BotState.get_current_pos()
location = new_vec3(cur_x, cur_y, cur_z)
offset = new_vec3(x, y, z)
Farmbot.CeleryScript.AST.Node.MoveAbsolute.execute(%{location: location, offset: offset, speed: speed}, [], env)

View File

@ -2,7 +2,7 @@ defmodule Farmbot.CeleryScript.Utils do
@moduledoc false
alias Farmbot.Firmware.Vec3
alias Farmbot.CeleryScript.AST
alias AST.Node.{Tool, Coordinate, Point}
alias AST.Node.{Tool, Coordinate, Point, Nothing}
alias Farmbot.Repo.Point, as: DBPoint
import Ecto.Query
@ -33,6 +33,10 @@ defmodule Farmbot.CeleryScript.Utils do
end
end
def ast_to_vec3(%AST{kind: Nothing}) do
{:ok, %Vec3{x: 0, y: 0, z: 0}}
end
def ast_to_vec3(%Vec3{} = vec3), do: {:ok, vec3}
def ast_to_vec3(%AST{kind: kind}) do

View File

@ -120,7 +120,7 @@ defmodule Farmbot.Mixfile do
defp deps(target) do
system(target) ++
[
{:bootloader, "~> 0.1.3"},
{:bootloader, "~> 0.1.3", except: :test},
{:nerves_runtime, "~> 0.4"},
{:nerves_firmware, "~> 0.4.0"},
{:nerves_firmware_ssh, "~> 0.2", only: :dev},

View File

@ -66,13 +66,13 @@ defmodule Farmbot.BotStateTest do
assert match?(:unknown, get_state(:informational_settings).sync_status)
end
# test "sets user environment" do
# key = "some_key"
# val = "hey! this should be in the bot's state!"
# :ok = BotState.set_user_env(key, val)
# res = BotState.get_user_env
# assert match?(%{^key => ^val}, res)
# end
test "sets user environment" do
key = "some_key"
val = "hey! this should be in the bot's state!"
:ok = BotState.set_user_env(key, val)
res = BotState.get_user_env
assert match?(%{^key => ^val}, res)
end
test "registers and unregisters farmware" do
name = "Not real farmware"

View File

@ -0,0 +1,7 @@
defmodule Farmbot.CeleryScript.AST.Arg.ElseTest do
use FarmbotTestSupport.AST.ArgTestCase
alias Farmbot.CeleryScript.AST
alias AST.Arg.Else
arg_is_ast(Else)
end

View File

@ -0,0 +1,7 @@
defmodule Farmbot.CeleryScript.AST.Arg.ThenTest do
use FarmbotTestSupport.AST.ArgTestCase
alias Farmbot.CeleryScript.AST
alias AST.Arg.Then
arg_is_ast(Then)
end

View File

@ -0,0 +1,40 @@
defmodule Farmbot.CeleryScript.AST.Arg.LhsTest do
use FarmbotTestSupport.AST.ArgTestCase
alias Farmbot.CeleryScript.AST.Arg.Lhs
test "encodes x axis" do
Lhs.encode(:x) |> assert_cs_arg_encode_ok("x")
end
test "encodes y axis" do
Lhs.encode(:y) |> assert_cs_arg_encode_ok("y")
end
test "encodes z axis" do
Lhs.encode(:z) |> assert_cs_arg_encode_ok("z")
end
test "decodes x axis" do
Lhs.decode("x") |> assert_cs_arg_decode_ok(:x)
end
test "decodes y axis" do
Lhs.decode("y") |> assert_cs_arg_decode_ok(:y)
end
test "decodes z axis" do
Lhs.decode("y") |> assert_cs_arg_decode_ok(:y)
end
test "encodes pin number" do
Lhs.encode({:pin, 13}) |> assert_cs_arg_encode_ok("pin13")
end
test "decodes pin number" do
Lhs.decode("pin13") |> assert_cs_arg_decode_ok({:pin, 13})
end
test "can't decode unknown data" do
Lhs.decode("some_other_lhs_arg") |> assert_cs_arg_decode_err
end
end

View File

@ -0,0 +1,7 @@
defmodule Farmbot.CeleryScript.AST.Arg.LocationTest do
use FarmbotTestSupport.AST.ArgTestCase
alias Farmbot.CeleryScript.AST
alias AST.Arg.Location
arg_is_ast(Location)
end

View File

@ -0,0 +1,7 @@
defmodule Farmbot.CeleryScript.AST.Arg.OffsetTest do
use FarmbotTestSupport.AST.ArgTestCase
alias Farmbot.CeleryScript.AST
alias AST.Arg.Offset
arg_is_ast(Offset)
end

View File

@ -0,0 +1,17 @@
defmodule Farmbot.CeleryScript.ASTTest do
use ExUnit.Case, async: true
alias Farmbot.CeleryScript.AST
@nothing_json "{\"kind\": \"nothing\", \"args\": {}}"
@bad_json "{\"whoops\": "
test "decodes ast from json" do
res = AST.decode(@nothing_json)
assert match?({:ok, %AST{}}, res)
end
test "won't decode ast from bad json" do
res = AST.decode(@bad_json)
assert match?({:error, :unknown_binary}, res)
end
end

View File

@ -0,0 +1,11 @@
defmodule Farmbot.CeleryScript.AST.Inspect do
use ExUnit.Case
alias Farmbot.CeleryScript.AST
@nothing_json "{\"kind\": \"nothing\", \"args\": {}}"
test "Inspects ast node" do
{:ok, %AST{} = ast} = AST.decode(@nothing_json)
assert inspect(ast, []) == "#Nothing<[]>"
end
end

View File

@ -0,0 +1,46 @@
defmodule Farmbot.CeleryScript.AST.Node.MoveAbsoluteTest do
alias Farmbot.CeleryScript.AST.Node.{Coordinate, MoveAbsolute}
use FarmbotTestSupport.AST.NodeTestCase, async: false
test "mutates env", %{env: env} do
args = %{
location: nothing(),
speed: 100,
offset: nothing()
}
{:ok, env} = MoveAbsolute.execute(args, [], env)
assert_cs_env_mutation(MoveAbsolute, env)
end
test "moves to a location with no offset", %{env: env} do
nothing = nothing()
{:ok, coordinate, env} = Coordinate.execute(%{x: 100, y: 123, z: -123}, [], env)
args = %{
location: coordinate,
speed: 100,
offset: nothing
}
MoveAbsolute.execute(args, [], env) |> assert_cs_success()
%{x: res_x, y: res_y, z: res_z} = Farmbot.BotState.get_current_pos()
assert res_x == coordinate.args.x
assert res_y == coordinate.args.y
assert res_z == coordinate.args.z
end
test "moves to a location with an offset", %{env: env} do
{:ok, location, env} = Coordinate.execute(%{x: 0, y: 0, z: 0}, [], env)
{:ok, offset, env} = Coordinate.execute(%{x: 100, y: 123, z: -123}, [], env)
args = %{
location: location,
speed: 100,
offset: offset
}
MoveAbsolute.execute(args, [], env) |> assert_cs_success()
%{x: res_x, y: res_y, z: res_z} = Farmbot.BotState.get_current_pos()
assert res_x == offset.args.x
assert res_y == offset.args.y
assert res_z == offset.args.z
end
end

View File

@ -0,0 +1,67 @@
defmodule FarmbotTestSupport.AST.ArgTestCase do
use ExUnit.CaseTemplate
defmodule ArgFuns do
def assert_cs_arg_decode_ok(res, val \\ nil) do
if val do
assert match?({:ok, ^val}, res)
else
assert match?({:ok, _}, res)
end
res
end
def assert_cs_arg_decode_err(res) do
assert match?({:error, _}, res)
res
end
def assert_cs_arg_encode_ok(res, val \\ nil) do
if val do
assert match?({:ok, ^val}, res)
else
assert match?({:ok, _}, res)
end
res
end
def assert_cs_encode_err(res) do
assert match?({:error, _}, res)
res
end
defmacro arg_is_ast(mod) do
quote do
@nothing_json "{\"kind\": \"nothing\", \"args\": {}}"
@mod unquote(mod)
alias Farmbot.CeleryScript.AST
test "decodes valid ast structure" do
res = @mod.decode(@nothing_json) |> assert_cs_arg_decode_ok()
assert match?({:ok, %AST{}}, res)
end
test "Won't decode bad data" do
@mod.decode("this isn't an ast node") |> assert_cs_arg_decode_err
end
test "encodes valid ast" do
{:ok, ast} = AST.decode(@nothing_json)
@mod.encode(ast) |> assert_cs_arg_decode_ok
end
test "wont encode bad data" do
@mod.encode("this isn't an ast node") |> assert_cs_encode_err
end
end
end
end
using do
quote do
import ArgFuns
end
end
end

View File

@ -27,6 +27,11 @@ defmodule FarmbotTestSupport.AST.NodeTestCase do
end
end
def nothing(env \\ struct(Macro.Env, [])) do
{:ok, res, _} = Farmbot.CeleryScript.AST.Node.Nothing.execute(%{}, [], env)
res
end
end
end

View File

@ -61,13 +61,15 @@ defmodule FarmbotTestSupport do
end
end
defp ping_mqtt(tkn) do
url = Farmbot.Jwt.decode!(tkn).mqtt
Logger.info("Preflight check: mqtt: #{url}")
# defp ping_mqtt(tkn) do
# url = Farmbot.Jwt.decode!(tkn).mqtt
# Logger.info("Preflight check: mqtt: #{url}")
#
# case :gen_tcp.connect(to_charlist(url), 1883, [:binary]) do
# {:error, _} -> :mqtt
# {:ok, port} -> :gen_tcp.close(port)
# end
# end
case :gen_tcp.connect(to_charlist(url), 1883, [:binary]) do
{:error, _} -> :mqtt
{:ok, port} -> :gen_tcp.close(port)
end
end
defp ping_mqtt(_), do: :ok
end

View File

@ -0,0 +1,15 @@
defmodule Farmbot.BotState.Transport.Test do
use GenStage
def start_link do
GenStage.start_link(__MODULE__, [], [name: __MODULE__])
end
def init([]) do
{:consumer, :no_state, subscribe_to: [Farmbot.BotState, Farmbot.Logger]}
end
def handle_events(_, _, state) do
{:noreply, [], state}
end
end