diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3d9d325 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true +indent_style = space +indent_size = 4 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..82956eb --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.beam binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4102184 --- /dev/null +++ b/.gitignore @@ -0,0 +1,100 @@ +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# network security +/network-security.data + + +### Erlang ### +.eunit +ebin +deps +*.o +*.beam +*.plt +erl_crash.dump +ebin/*.beam +rel/example_project +.concrete/DEV_MODE +.rebar +_build +_checkouts +doc +.rebar3 +*.crashdump + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Custom +.envrc diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..796c58c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: erlang +otp_release: + - 21.3 + - 22.1 +script: + - rebar3 check + +cache: + directories: + - "$HOME/.cache/rebar3" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e726fab --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +Copyright © 2019 Antoine Gagné +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +3. Neither the name of the organization nor the +names of its contributors may be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Antoine Gagné ''AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Antoine Gagné BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..0316ae1 --- /dev/null +++ b/README.rst @@ -0,0 +1,76 @@ +============== +mqtt-simulator +============== + +.. image:: https://travis-ci.org/AntoineGagne/mqtt-simulator.svg?branch=master + :target: https://travis-ci.org/AntoineGagne/mqtt-simulator + +.. image:: https://ci.appveyor.com/api/projects/status/glyeekdu4vum33ht/branch/master?svg=true + :target: https://ci.appveyor.com/api/projects/status/glyeekdu4vum33ht/branch/master + +:Author: `Antoine Gagné `_ + +.. contents:: + :backlinks: none + +.. sectnum:: + +Installation +============ + +Local Build +----------- + +To build the runnable release, you need to have Erlang with OTP 21 and above. +You also need ``rebar3``. Then, you can run the following command: + +.. code-block:: sh + + rebar3 as prod release + +Docker Image +------------ + +To build this image, you can use the following command: + +.. code-block:: sh + + docker build -f Dockerfile -t "${name_of_the_image}" . + +Usage +===== + +From Local Build +---------------- + +If you built the release, you can run it with: + +.. code-block:: sh + + ./_build/prod/rel/mqtt_simulator/bin/mqtt_simulator foreground + + +Docker +------ + +After building the image, you can run the image by using the following command: + +.. code-block:: sh + + docker run \ + --detach \ + --name "${name_of_the_running_container}" \ + --publish "${port_on_host}:${port_of_simulator:-8000}" \ + "${name_of_the_image}" + +Development +=========== + +Running all the tests and linters +--------------------------------- + +You can run all the tests and linters with the ``rebar3`` alias: + +.. code-block:: sh + + rebar3 check diff --git a/rebar.config b/rebar.config new file mode 100644 index 0000000..1927148 --- /dev/null +++ b/rebar.config @@ -0,0 +1,88 @@ +{alias, [ + {check, [lint, xref, dialyzer, edoc, + {eunit, "-c"}, {ct, "-c"}, {proper, "-c"}, + {cover, "-v --min_coverage=0"}, + todo + ]} + ]}. + +{dialyzer, [{warnings, [unknown]}]}. + +{erl_opts, [ + debug_info, + warn_unused_import, + warnings_as_errors + ]}. + +{deps, [] +}. + +{profiles, [{prod, [{relx, [{dev_mode, false}, + {include_erts, true}]}] + }, + + {test, [ + {erl_opts, [nowarn_export_all]}, + {deps, [ + {meck, "0.8.9"}, + {proper, {git, "https://github.com/manopapad/proper.git", {branch, "master"}}} + ]} + ]} + ] +}. + +{plugins, [ + {rebar3_proper, "0.11.1"}, + {rebar3_lint, {git, "https://github.com/project-fifo/rebar3_lint.git", {tag, "0.1.2"}}}, + {rebar3_todo, {git, "https://github.com/ferd/rebar3_todo.git", {branch, "master"}}} + ]}. + +{elvis, + [#{dirs => ["apps/*/src/**", + "apps/*/test/**"], + filter => "*.erl", + rules => [{elvis_style, line_length, + #{ignore => [], + limit => 120, + skip_comments => false}}, + {elvis_style, no_tabs}, + {elvis_style, no_trailing_whitespace}, + {elvis_style, macro_names, #{ignore => []}}, + {elvis_style, macro_module_names}, + {elvis_style, operator_spaces, #{rules => [{right, ","}, + {right, "++"}, + {left, "++"}]}}, + {elvis_style, nesting_level, #{level => 3}}, + {elvis_style, god_modules, + #{limit => 25, + ignore => []}}, + {elvis_style, no_if_expression}, + {elvis_style, invalid_dynamic_call, + #{ignore => []}}, + {elvis_style, used_ignored_variable}, + {elvis_style, no_behavior_info}, + {elvis_style, + module_naming_convention, + #{regex => "^[a-z]([a-z0-9]*_?)*(_SUITE)?$", ignore => []}}, + {elvis_style, + function_naming_convention, + #{regex => "^[a-z]([a-z0-9]*_?)*$"}}, + {elvis_style, state_record_and_type}, + {elvis_style, no_spec_with_records}, + {elvis_style, dont_repeat_yourself, #{min_complexity => 20}}, + {elvis_style, no_debug_call, #{ignore => []}} + ] + }, + #{dirs => ["."], + filter => "rebar.config", + rules => [{elvis_project, no_deps_master_rebar, #{ignore => []}}] + } + ] +}. + +{xref_checks,[undefined_function_calls, + undefined_functions, + locals_not_used, + deprecated_function_calls, + deprecated_functions]}. +{xref_ignores, []}. diff --git a/rebar.lock b/rebar.lock new file mode 100644 index 0000000..57afcca --- /dev/null +++ b/rebar.lock @@ -0,0 +1 @@ +[]. diff --git a/src/robots.app.src b/src/robots.app.src new file mode 100644 index 0000000..95f5241 --- /dev/null +++ b/src/robots.app.src @@ -0,0 +1,14 @@ +{application, robots, + [{description, "An OTP library"}, + {vsn, "0.1.0"}, + {registered, []}, + {applications, + [kernel, + stdlib + ]}, + {env,[]}, + {modules, []}, + + {licenses, ["Apache 2.0"]}, + {links, []} + ]}. diff --git a/src/robots.erl b/src/robots.erl new file mode 100644 index 0000000..87600bc --- /dev/null +++ b/src/robots.erl @@ -0,0 +1,24 @@ +-module(robots). + +-export([parse/2]). + +-type agent() :: string() | binary(). +-type rule() :: string() | binary(). +-type rules() :: sets:set(rule()). +-type content() :: string() | binary(). +-type status() :: allowed | disallowed. +-type agent_rules() :: #{agent() := {Allowed :: rules(), Disallowed :: rules()}}. +-type code() :: 400..599. + +-spec parse(content(), code()) -> {ok, {status(), all} | {rules, agent_rules()}} | {error, term()}. +parse(_Content, Code) when Code >= 500 andalso Code < 600 -> + {ok, {disallowed, all}}; +parse(_Content, Code) when Code >= 400 -> + {ok, {allowed, all}}; +parse(Content, Code) when Code >= 200 andalso Code < 300 -> + build_rules(Content); +parse(_Content, Code) -> + {error, {invalid_status_code, Code}}. + +build_rules(_Content) -> + {ok, {rules, #{}}}. diff --git a/test/prop_robots.erl b/test/prop_robots.erl new file mode 100644 index 0000000..002c927 --- /dev/null +++ b/test/prop_robots.erl @@ -0,0 +1,11 @@ +-module(prop_robots). + +-include_lib("proper/include/proper.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-compile(nowarn_export_all). +-compile(export_all). + +%%%=================================================================== +%%% Generators +%%%=================================================================== diff --git a/test/robots_SUITE.erl b/test/robots_SUITE.erl new file mode 100644 index 0000000..5cb69aa --- /dev/null +++ b/test/robots_SUITE.erl @@ -0,0 +1,22 @@ +-module(robots_SUITE). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). + +-compile(nowarn_export_all). +-compile(export_all). + +all() -> + [ + ]. + +init_per_testcase(_Name, Config) -> + Config. + +end_per_testcase(_Name, Config) -> + Config. + + +%%%=================================================================== +%%% Internal functions +%%%===================================================================