whitfin / local-cluster Goto Github PK
View Code? Open in Web Editor NEWEasy local cluster creation for Elixir to aid in unit testing
License: MIT License
Easy local cluster creation for Elixir to aid in unit testing
License: MIT License
I wrote a simplified version of a test based on the documentation, over here: https://github.com/whitfin/local-cluster#usage
However, when I run the test it fails (message not received), and I see the following error in stdout:
$ mix test
.
10:03:57.708 [error] Process #PID<20934.220.0> on node :"[email protected]" raised an exception
** (UndefinedFunctionError) undefined function
#Function<0.60679234/0 in ChatTest."test test node things"/1>()
10:03:57.708 [error] Process #PID<0.220.0> on node :"[email protected]" raised an exception
** (UndefinedFunctionError) undefined function
#Function<0.60679234/0 in ChatTest>()
1) test test node things (ChatTest)
test/chat_test.exs:5
Assertion failed, no matching message after 100ms
The process mailbox is empty.
code: assert_receive :a_message_from_the_node
stacktrace:
test/chat_test.exs:14: (test)
Finished in 3.1 seconds (0.00s async, 3.1s sync)
1 doctest, 1 test, 1 failure
Randomized with seed 660329
My test looks as follows:
defmodule ChatTest do
use ExUnit.Case
doctest Chat
test "test node things" do
[n1, _n2, _n3] = LocalCluster.start_nodes("my-cluster", 3)
caller = self()
_n1_pid = Node.spawn(n1, fn ->
send(caller, :a_message_from_the_node)
end)
assert_receive :a_message_from_the_node
end
end
My test_helper.exs:
# start the current node as a manager
:ok = LocalCluster.start()
# start your application tree manually
Application.ensure_all_started(:my_app)
# run all tests!
ExUnit.start()
My mix.exs:
defmodule Chat.MixProject do
use Mix.Project
def project do
[
app: :chat,
version: "0.1.0",
elixir: "~> 1.14",
start_permanent: Mix.env() == :prod,
deps: deps(),
aliases: [
test: "test --no-start"
]
]
end
def application do
[
extra_applications: [:logger],
mod: {Chat.Application, []}
]
end
defp deps do
[
{:local_cluster, "~> 1.2", only: [:test]}
]
end
end
My elixir version:
$ elixir --version
Erlang/OTP 25 [erts-13.0.4] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit]
Elixir 1.14.0 (compiled with Erlang/OTP 25)
Anything obvious that I'm doing wrong?
I get the same behavior when I use receive do ...
instead of assert_receive
When I delete the assert_receive line, I don't get the 'undefined function` error anymore.
When running LocalCluster.start/0
I get the following error:
{:error,
{{:shutdown, {:failed_to_start_child, :net_kernel, {:EXIT, :nodistribution}}},
{:child, :undefined, :net_sup_dynamic,
{:erl_distribution, :start_link, [[:"[email protected]"], false]},
:permanent, 1000, :supervisor, [:erl_distribution]}}}
I followed the getting started guide, other then that I have a pretty simple phoenix app with some other deps.
This is my Elixir and Erlang/OTP version:
Erlang/OTP 21 [erts-10.3] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]
Elixir 1.8.1 (compiled with Erlang/OTP 21)
Any clue?
Some systems generate cookies that have special characters in them, this trips the shell when supplying that cookie with the -setcookie
option.
For example, I have the cookie 0mwHxf/~5h{?|pm<ST1PCtean_Be~bT9386.5O9!RL2s5=[YkPLCew%^@[A&CO^x
, and shell outputs these errors:
sh: ST1PCtean_Be~bT9386.5O9!RL2s5=[YkPLCew%^@[A: No such file or directory
sh: CO^x: command not found
This is easily fixed by wrapping the cookie with quotes.
I am working on a Spawnfest idea and I am using LocalCluster to test the distribution. If I start my supervision tree implicitly (with the :mod
key), then Application.ensure_started
works and LocalCluster's doc document as much (started applications are replicated to slave nodes).
But how does it work if I don't want to start my app up implicitly? Instead of starting it implicitly, I am requiring users to put it in their supervision tree. In my test, I can manually call start_link
to start it which is pretty neat, but when LocalCluster is involved, I am not able to get these supervision tree started there.
I tried to do a :rpc.call(node1, MySupervisor, :start_link, [])
but that doesn't work either, is it not possible?
Is there a way to start the nodes with test env (MIX_ENV=test)?
I'm using Swarm as a dependency, and by default it logs a lot of data when running in dev mode (info and debug).
While using Local Cluster in a test, I can see all the logs Swarm produces from all nodes on the test cluster as they're running with dev environment.
Is there a way to prevent all these logs to appear during tests but keep them for dev?
I was following the readme to the letter recently by running LocalCluster.start
before my ExUnit.start
in the test_helper (Phoenix) but ... strangely enough it turns out you can run the LocalCluster.start
in a single setup for just 1 test meaning the ExUnit.start
can remain in the test_helper as you would see in any default application layout.
Any reason we can't update the readme to reflect this^ world view?
note: working example app w/ my results to prove its fine running after ExUnit.start
I see that application configs are passed to spawned nodes here
local-cluster/lib/local_cluster.ex
Line 70 in f86e6f0
some umbrella app somehow is getting started before this line is executed
local-cluster/lib/local_cluster.ex
Line 70 in f86e6f0
some umbrella app is not loaded (and loading later with missing config)
local-cluster/lib/local_cluster.ex
Line 68 in f86e6f0
is it possible?
I'd like to use this library not inside unit-tests, but inside some integration tests that ensure that the core functionality of our distributed application (https://planga.io) keeps functioning within expected bounds, even if the connection between nodes is slow, or if from time to time requests are being dropped.
What do you think? ๐
Hi, I'm using https://github.com/bitwalker/libcluster to setup, well, the cluster ๐
But, for some reason, creating nodes from test via LocalCluster.start_nodes("my_cluster", 2)
doesn't pick up libcluster
configuration.
In config/config.exs
I have:
config :my_app, MyAppWeb.Endpoint,
...
config :libcluster,
topologies: [
local: [
strategy: Cluster.Strategy.Gossip,
connect: {:net_kernel, :connect_node, []},
disconnect: {:erlang, :disconnect_node, []},
list_nodes: {:erlang, :nodes, [:connected]}
]
]
And in application.ex
I use topologies = Application.fetch_env!(:libcluster, :topologies)
to fetch that configuration and supply it to libcluster
. However, :libcluster
configuration is empty for nodes created via LocalCluster
. At the same time, it is properly picked up when project is started in dev/prod mode and manager
node started with tests also picks it up correctly.
In test helper I have:
:ok = LocalCluster.start()
Application.ensure_all_started(:my_app)
ExUnit.start()
Note that if I change the configuration to config :my_app
instead of config :libcluster
, it all works correctly (configuration is picked up). So there is a workaround, but I'd still like to be able to set the config key properly. Funny thing is, e.g. config :logger
is correctly picked up.
The title here is probably more of a potential solution then the underlying problem.
In a lot of my tests I need to ensure that nodes discover and connect to each other. But when local cluster the primary node connects to the other nodes and creates a full mesh between all of the existing nodes. I'm not even sure if what I want to do is possible but I'm wondering if there's a programatic way to start the main node as a hidden node or something similar so that the cluster behaves as though the main node isn't truly a part of the cluster. I know that you can pass an erl flag to set a node as hidden but I'm not sure if you can do that once the node is already booted.
I might be going in a totally wrong direction here (and if so please tell me so) but I wanted to get your thoughts on it.
Hello!
Tried this library and got permanent :not_alive error on LocalCluster.start_nodes
Also your library test returned this
00:02:37.767 [info] Protocol 'inet_tcp': register/listen error: econnrefused
** (MatchError) no match of right hand side value: {:error, {{:shutdown, {:failed_to_start_child, :net_kernel, {:EXIT, :nodistribution}}}, {:child, :undefined, :net_sup_dynamic, {:erl_distribution, :start_link, [[:"manager@1
27.0.0.1"], false]}, :permanent, 1000, :supervisor, [:erl_distribution]}}}
test/test_helper.exs:2: (file)
(elixir) lib/code.ex:813: Code.require_file/2
(elixir) lib/enum.ex:783: Enum."-each/2-lists^foreach/1-0-"/2
I am not sure - may be this issue is trivial and self obvious for true erlang developers, but for noobs like me it was kind of pain.
Finally I got the reason - there must be epmd
daemon running.
So may be reflect this requirements in documentation? It seems mandatory condition so looks logical for me to write couple of lines about it.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.