Created
November 16, 2019 07:52
-
-
Save koduki/fb15ca78d6715fa60f01306382e1efff to your computer and use it in GitHub Desktop.
Elixirで書いてみた簡易な負荷テストツール
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule LoadGenerator do | |
import AssertionHelper | |
import LogHelper | |
import RestHelper | |
def run(users_num) do | |
Enum.map(1..users_num, fn(x) -> Task.async(fn -> make_user() end)end) | |
|> Enum.map(fn(task) -> Task.await(task, 1_000_000) end) | |
end | |
def make_user() do | |
accountNo = req_origination() | |
# run test senario | |
loop_count = :rand.uniform(10) | |
IO.puts("loop count: #{loop_count}") | |
senario001(0, 0, loop_count, accountNo) | |
end | |
def senario001(count, sum, loop_count, accountNo) when loop_count > 0 do | |
# pay | |
amount1 = :rand.uniform(100_000) | |
transactionId1 = req_authorize(accountNo, amount1) | |
amount2 = :rand.uniform(10_000) | |
transactionId2 = req_authorize(accountNo, amount2) | |
# show summary | |
body = req_summary(accountNo, 11) | |
assert = assert_template(body) | |
# validate | |
count = count + 2 | |
sum = sum + amount1 + amount2 | |
r = it("test result", [ | |
assert.("accountNo", :should_be, accountNo), | |
assert.("count", :should_be, count), | |
assert.("summary", :should_be, sum) | |
]) | |
interval = :rand.uniform(2000) | |
:timer.sleep(interval) | |
senario001(count, sum, loop_count - 1, accountNo) ++ [r] | |
end | |
def senario001(count, sum, loop_count, accountNo) do | |
[] | |
end | |
def req_origination do | |
# origination | |
{t, {:http_ok, body}} = post("http://app:8080/account/create", []) | |
body["accountNo"] | |
end | |
def req_authorize(accountNo, amount) do | |
req = Jason.encode!(%{"accountNo" => accountNo, "amount" => amount, "usedDateTime" => "2019-11-15T06:51:19.918Z"}) | |
{t, {:http_ok, body}} = post("http://app:8080/payment/authorize", req) | |
body["transactionId"] | |
end | |
def req_summary(accountNo, usedMonth) do | |
{t, {:http_ok, r}} = get("http://app:8080/account/#{accountNo}/summary/#{usedMonth}", []) | |
r | |
end | |
end | |
defmodule AssertionHelper do | |
def assert_template(r) do | |
fn (key, operation, expectation) -> {"#{key} should be #{expectation}", r[key] == expectation} end | |
end | |
def it(title, actuals) do | |
{ | |
Enum.all?(actuals, fn(x) -> elem(x,1) end), | |
Enum.into(actuals, %{}) | |
} | |
end | |
end | |
defmodule LogHelper do | |
def log(message) do | |
Task.async(fn -> IO.inspect(message) end) | |
end | |
end | |
defmodule RestHelper do | |
import LogHelper | |
def get(url, req) do | |
{_,s}=DateTime.now("Etc/UTC") | |
{t, r} = :timer.tc(fn -> | |
case HTTPoison.get(url, req, []) do | |
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> {:http_ok, Jason.decode!(body)} | |
_ -> {:error, nil} | |
end | |
end) | |
{_,e}=DateTime.now("Etc/UTC") | |
log({(if t <= 3_000_000, do: :ok, else: :timeout), elem(r, 0), [url: url, method: :get, response: t, start_time: s, end_time: e]}) | |
{t, r} | |
end | |
def post(url, req) do | |
{_,s}=DateTime.now("Etc/UTC") | |
{t, r} = :timer.tc(fn -> | |
case HTTPoison.post(url, req, [{"Content-Type", "application/json"}]) do | |
{:ok, %HTTPoison.Response{status_code: 200, body: body}} -> {:http_ok, Jason.decode!(body)} | |
_ -> {:http_error, nil} | |
end | |
end) | |
{_,e}=DateTime.now("Etc/UTC") | |
log({(if t <= 3_000_000, do: :ok, else: :timeout), elem(r, 0), [url: url, method: :post, response: t, start_time: s, end_time: e]}) | |
{t, r} | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment