diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..06e85d5 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,17 @@ +version: 2.0 +jobs: + build: + docker: + - image: membrane/membrane:latest + environment: + MIX_ENV: test + + working_directory: ~/app + + steps: + - checkout + - run: mix deps.get + - run: mix format --check-formatted + - run: mix compile --force --warnings-as-errors + - run: mix test + - run: MIX_ENV=dev mix docs && ! mix docs 2>&1 | grep -q "warning:" diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e310ff5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 100 +tab_width = 2 +trim_trailing_whitespace = true diff --git a/.formatter.exs b/.formatter.exs new file mode 100644 index 0000000..4c3febe --- /dev/null +++ b/.formatter.exs @@ -0,0 +1,8 @@ +[ + inputs: [ + "{lib,test,config}/**/*.{ex,exs}", + ".formatter.exs", + "*.exs" + ], + import_deps: [:membrane_core] +] diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2436cb --- /dev/null +++ b/.gitignore @@ -0,0 +1,176 @@ +compile_commands.json +.gdb_history +bundlex.sh +bundlex.bat + +# Created by https://www.gitignore.io/api/c,vim,linux,macos,elixir,windows,visualstudiocode +# Edit at https://www.gitignore.io/?templates=c,vim,linux,macos,elixir,windows,visualstudiocode + +### C ### +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf + +### Elixir ### +/_build +/cover +/deps +/doc +/.fetch +erl_crash.dump +*.ez +*.beam +/config/*.secret.exs +.elixir_ls/ + +### Elixir Patch ### + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### 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 +Sessionx.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 + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.gitignore.io/api/c,vim,linux,macos,elixir,windows,visualstudiocode diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..518cbb5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Software Mansion + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md new file mode 100644 index 0000000..47e23b6 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +# Membrane Multimedia Framework: Interactive Connectivity Establishment (ICE) Implementation + +[![Hex.pm](https://img.shields.io/hexpm/v/membrane_ice.svg)](https://hex.pm/packages/membrane_ice) +[![CircleCI](https://circleci.com/gh/membraneframework/membrane_ice.svg?style=svg)](https://circleci.com/gh/membraneframework/membrane_ice) + +This package provides a wrapper over [libnice] and GStreamer-style ICE source & sink elements. + +It is part of [Membrane Multimedia Framework](https://membraneframework.org). + +## Installation + +The package can be installed by adding `membrane_ice` to your list of dependencies in `mix.exs`: + +```elixir +def deps do + [ + {:membrane_ice, "~> 0.1.0"} + ] +end +``` + +## Usage + +TODO + +## Copyright and License + +Copyright 2020, [Software Mansion](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_ice) + +[![Software Mansion](https://logo.swmansion.com/logo?color=white&variant=desktop&width=200&tag=membrane-github)](https://swmansion.com/?utm_source=git&utm_medium=readme&utm_campaign=membrane_ice) + +Licensed under the [Apache License, Version 2.0](LICENSE) + +[libnice]: https://libnice.freedesktop.org/ diff --git a/bundlex.exs b/bundlex.exs new file mode 100644 index 0000000..ebb0292 --- /dev/null +++ b/bundlex.exs @@ -0,0 +1,18 @@ +defmodule Membrane.ICE.BundlexProject do + use Bundlex.Project + + def project do + [ + nifs: nifs(Bundlex.platform()) + ] + end + + defp nifs(_platform) do + [ + native: [ + sources: ["native.c", "_generated/native.c"], + deps: [membrane_common_c: :membrane, unifex: :unifex] + ] + ] + end +end diff --git a/c_src/membrane_ice/_generated/.gitignore b/c_src/membrane_ice/_generated/.gitignore new file mode 100644 index 0000000..68359a7 --- /dev/null +++ b/c_src/membrane_ice/_generated/.gitignore @@ -0,0 +1,2 @@ +*.c +*.h diff --git a/c_src/membrane_ice/native.c b/c_src/membrane_ice/native.c new file mode 100644 index 0000000..e69de29 diff --git a/c_src/membrane_ice/native.h b/c_src/membrane_ice/native.h new file mode 100644 index 0000000..c22f239 --- /dev/null +++ b/c_src/membrane_ice/native.h @@ -0,0 +1,16 @@ +#pragma once + +#define MEMBRANE_LOG_TAG "Membrane.ICE.Native" + +#include +#include + +typedef struct _NativeState UnifexNifState; +typedef UnifexNifState State; + +struct _NativeState +{ + //TODO +}; + +#include "_generated/native.h" diff --git a/c_src/membrane_ice/native.spec.exs b/c_src/membrane_ice/native.spec.exs new file mode 100644 index 0000000..812b25f --- /dev/null +++ b/c_src/membrane_ice/native.spec.exs @@ -0,0 +1 @@ +module Membrane.ICE.Native diff --git a/lib/membrane_ice/template.ex b/lib/membrane_ice/template.ex new file mode 100644 index 0000000..53fce80 --- /dev/null +++ b/lib/membrane_ice/template.ex @@ -0,0 +1,2 @@ +defmodule Membrane.ICE.Template do +end diff --git a/mix.exs b/mix.exs new file mode 100644 index 0000000..3dc3d61 --- /dev/null +++ b/mix.exs @@ -0,0 +1,68 @@ +defmodule Membrane.ICE.Mixfile do + use Mix.Project + + @version "0.1.0" + @github_url "https://github.com/membraneframework/membrane_ice" + + def project do + [ + app: :membrane_ice, + version: @version, + elixir: "~> 1.9", + compilers: [:unifex, :bundlex] ++ Mix.compilers(), + elixirc_paths: elixirc_paths(Mix.env()), + start_permanent: Mix.env() == :prod, + deps: deps(), + + # hex + description: "Interactive Connectivity Establishment (ICE) implementation for Membrane Multimedia Framework", + package: package(), + + # docs + name: "Membrane: ICE", + source_url: @github_url, + homepage_url: "https://membraneframework.org", + docs: docs() + ] + end + + def application do + [ + extra_applications: [] + ] + end + + defp elixirc_paths(:test), do: ["lib", "test/support"] + defp elixirc_paths(_env), do: ["lib"] + + defp deps do + [ + {:membrane_core, "~> 0.5.0"}, + {:membrane_common_c, "~> 0.3.0"}, + {:unifex, "~> 0.2.6"}, + {:ex_doc, "~> 0.22", only: :dev, runtime: false}, + {:dialyxir, "~> 1.0.0", only: :dev, runtime: false} + ] + end + + defp package do + [ + maintainers: ["Membrane Team"], + licenses: ["Apache 2.0"], + links: %{ + "GitHub" => @github_url, + "Membrane Framework Homepage" => "https://membraneframework.org" + }, + files: ["lib", "mix.exs", "README*", "LICENSE*", ".formatter.exs", "bundlex.exs", "c_src"] + ] + end + + defp docs do + [ + main: "readme", + extras: ["README.md"], + source_ref: "v#{@version}", + nest_modules_by_prefix: [Membrane.ICE] + ] + end +end diff --git a/mix.lock b/mix.lock new file mode 100644 index 0000000..0a18e3b --- /dev/null +++ b/mix.lock @@ -0,0 +1,21 @@ +%{ + "bunch": {:hex, :bunch, "1.3.0", "51b4423088b7fb9e21eae6d6bc5e5d219d955ea5556fbd6130bfb6213df4be32", [:mix], [], "hexpm", "9ad233a2bacc0dae8aa6553a9b9057f27446443b1c5903c3479b6f9f3820ce2d"}, + "bunch_native": {:hex, :bunch_native, "0.2.1", "0227d2a751a32f8c0b77dfec57c8dc7216351720c9c755c467e6d9387467fd1f", [:mix], [{:bundlex, "~> 0.2.7", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "f0819b2f9f78086447ac7459a8e7b6e25ad535b9d3a4f9469253c552137de6b4"}, + "bundlex": {:hex, :bundlex, "0.2.8", "0f4530bf24a2ebb92f2e360111319aae6fc6eb03c6ec5054b529d9ffb78811fa", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.5", [hex: :qex, repo: "hexpm", optional: false]}, {:secure_random, "~> 0.5", [hex: :secure_random, repo: "hexpm", optional: false]}], "hexpm", "d583b04ea679297aa08ad2b31866c4848fd99feea036bf5af59df71e2408b096"}, + "coerce": {:hex, :coerce, "1.0.1", "211c27386315dc2894ac11bc1f413a0e38505d808153367bd5c6e75a4003d096", [:mix], [], "hexpm", "b44a691700f7a1a15b4b7e2ff1fa30bebd669929ac8aa43cffe9e2f8bf051cf1"}, + "dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"}, + "earmark": {:hex, :earmark, "1.4.5", "62ffd3bd7722fb7a7b1ecd2419ea0b458c356e7168c1f5d65caf09b4fbdd13c8", [:mix], [], "hexpm", "b7d0e6263d83dc27141a523467799a685965bf8b13b6743413f19a7079843f4f"}, + "erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"}, + "ex_doc": {:hex, :ex_doc, "0.22.1", "9bb6d51508778193a4ea90fa16eac47f8b67934f33f8271d5e1edec2dc0eee4c", [:mix], [{:earmark, "~> 1.4.0", [hex: :earmark, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}], "hexpm", "d957de1b75cb9f78d3ee17820733dc4460114d8b1e11f7ee4fd6546e69b1db60"}, + "makeup": {:hex, :makeup, "1.0.3", "e339e2f766d12e7260e6672dd4047405963c5ec99661abdc432e6ec67d29ef95", [:mix], [{:nimble_parsec, "~> 0.5", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "2e9b4996d11832947731f7608fed7ad2f9443011b3b479ae288011265cdd3dad"}, + "makeup_elixir": {:hex, :makeup_elixir, "0.14.1", "4f0e96847c63c17841d42c08107405a005a2680eb9c7ccadfd757bd31dabccfb", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "f2438b1a80eaec9ede832b5c41cd4f373b38fd7aa33e3b22d9db79e640cbde11"}, + "membrane_common_c": {:hex, :membrane_common_c, "0.3.0", "eb17da0e469eacb8f4afbfc47752bd80d749397951d971cd1df67332a5cf77c6", [:mix], [{:bundlex, "~> 0.2.0", [hex: :bundlex, repo: "hexpm", optional: false]}, {:membrane_core, "~> 0.5.0", [hex: :membrane_core, repo: "hexpm", optional: false]}, {:shmex, "~> 0.2.0", [hex: :shmex, repo: "hexpm", optional: false]}, {:unifex, "~> 0.2.0", [hex: :unifex, repo: "hexpm", optional: false]}], "hexpm", "4c09fd3d802aa36f65225778b1fe819d63df835ac6c113a2be1222ab454175bb"}, + "membrane_core": {:hex, :membrane_core, "0.5.2", "c657e184dc330f8c533d6592615800319802e1c0081c8589020f46ecd77cc35a", [:mix], [{:bunch, "~> 1.2", [hex: :bunch, repo: "hexpm", optional: false]}, {:qex, "~> 0.3", [hex: :qex, repo: "hexpm", optional: false]}, {:ratio, "~> 2.0", [hex: :ratio, repo: "hexpm", optional: false]}], "hexpm", "51c2e67b1764296a7aee50a3c3aef9a3da5a9c34dd01f969e90f2896eff9ae15"}, + "nimble_parsec": {:hex, :nimble_parsec, "0.6.0", "32111b3bf39137144abd7ba1cce0914533b2d16ef35e8abc5ec8be6122944263", [:mix], [], "hexpm", "27eac315a94909d4dc68bc07a4a83e06c8379237c5ea528a9acff4ca1c873c52"}, + "numbers": {:hex, :numbers, "5.2.1", "8a6e9eeacfb19f4ac30a52c304f565dc53f8e0813b7193812a5b15b93210780c", [:mix], [{:coerce, "~> 1.0", [hex: :coerce, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "1fd66efe26b67456ad0b80a038f553b89702d073a6942ecd34ce1a3e10af4c92"}, + "qex": {:hex, :qex, "0.5.0", "5a3a9becf67d4006377c4c247ffdaaa8ae5b3634a0caadb788dc24d6125068f4", [:mix], [], "hexpm", "4ad6f6421163cd8204509a119a5c9813cbb969cfb8d802a9dc49b968bffbac2a"}, + "ratio": {:hex, :ratio, "2.4.1", "ecf989f3a1483cf892b867ab00ffe8e0784cbe748cd32a610a4ac4c4fd11f46d", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}, {:numbers, "~> 5.2.0", [hex: :numbers, repo: "hexpm", optional: false]}], "hexpm", "3988235b59285b8fef9a55867c0b82125b59915ac80808de064b33ff57b0d54c"}, + "secure_random": {:hex, :secure_random, "0.5.1", "c5532b37c89d175c328f5196a0c2a5680b15ebce3e654da37129a9fe40ebf51b", [:mix], [], "hexpm", "1b9754f15e3940a143baafd19da12293f100044df69ea12db5d72878312ae6ab"}, + "shmex": {:hex, :shmex, "0.2.1", "f60f4edc85e514d131ceff1acd37a2b3ff8e77c88d7c04a05b8ab2ba454a1a40", [:mix], [{:bunch_native, "~> 0.2.0", [hex: :bunch_native, repo: "hexpm", optional: false]}, {:bundlex, "~> 0.2.8", [hex: :bundlex, repo: "hexpm", optional: false]}], "hexpm", "8e75c2e2fd5735b57a66384ee4e9adb2888675074eacf01c63b71032387d4c65"}, + "unifex": {:hex, :unifex, "0.2.6", "d351fb329a08044913eafaeb1e98193545744207172b58e61678ff297a231c6d", [:mix], [{:bunch, "~> 1.0", [hex: :bunch, repo: "hexpm", optional: false]}, {:bundlex, "~> 0.2.0", [hex: :bundlex, repo: "hexpm", optional: false]}, {:shmex, "~> 0.2.0", [hex: :shmex, repo: "hexpm", optional: false]}], "hexpm", "50b233645324c8658cfc2feaf87083c477b097ccc5420b9cbf3f2e495cb5c0b0"}, +} diff --git a/test/test_helper.exs b/test/test_helper.exs new file mode 100644 index 0000000..869559e --- /dev/null +++ b/test/test_helper.exs @@ -0,0 +1 @@ +ExUnit.start()