Skip to content

Unibeam test single

Unibeam Test Script for wrk (Single MSISDN)ยถ

unibeam_test_single.lua
-- === CONFIG ===
local NUM_MSISDNS = 1
local BASE_URL = "https://api.il.unibeam.com"
local CALLBACK_URL = "https://roiwebhook.unibeam.us/callback"
local CUSTOMER_ID = "roi"
local AUTH_USERNAME = "unibeam"
local AUTH_PASSWORD = "abcd1234"
local MESSAGE = "hello7"
local TEMPLATE_ID = "login1"

-- === TOKEN CONFIG ===
local token_expiration_minutes = 60                      -- how long the token is valid
local token_valid_for = token_expiration_minutes * 60  -- seconds
local token_fetched_at = 0                              -- UNIX timestamp when token was fetched

-- === GLOBALS ===
local msisdns = (function()
  local list = {}
  for i = 1, NUM_MSISDNS do
    list[i] = tostring(i)
  end
  return list
end)()

local token = nil
local authenticated = false
local api_paths = {
  "/api/v1/business/transaction-multisecure",
  "/api/v1/business/transaction-touch",
  "/api/v1/auth/silent",
  "/api/v1/auth/touch"
}

local api_index = 1
local msisdn_index = 1
local threads = {}

-- === UTILS ===
local function uuid()
  local template = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
  return string.gsub(template, "[xy]", function(c)
    local v = (c == "x") and math.random(0, 15) or math.random(8, 11)
    return string.format("%x", v)
  end)
end

-- === SETUP ===
function setup(thread)
  local threadId = 0
  if thread and type(thread.id) == "function" then
    threadId = thread:id()
  elseif thread and type(thread) == "table" and type(thread.thread) == "number" then
    threadId = thread.thread
  end

  math.randomseed(os.time() + threadId)
  table.insert(threads, thread)
end

-- === REQUEST ===
function request()
  local now = os.time()
  local token_expired = (not token_fetched_at) or (now - token_fetched_at >= token_valid_for)

  if not authenticated or token_expired then
    authenticated = false
    token = nil
    local body = string.format('{"username":"%s","password":"%s"}', AUTH_USERNAME, AUTH_PASSWORD)
    return wrk.format("POST", "/authenticate", {
      ["Content-Type"] = "application/json",
      ["customerId"] = CUSTOMER_ID
    }, body)
  end

  local msisdn = msisdns[msisdn_index]
  local reqId = uuid()
  local path = api_paths[api_index]
  local body

  if api_index == 1 then
    body = string.format([[{
      "msisdn":"%s",
      "cbUrl":"%s",
      "requestId":"%s",
      "message":"%s",
      "rejectOnActiveCall":false
    }]], msisdn, CALLBACK_URL, reqId, MESSAGE)

  elseif api_index == 2 then
    body = string.format([[{
      "msisdn":"%s",
      "cbUrl":"%s",
      "requestId":"%s",
      "message":"%s"
    }]], msisdn, CALLBACK_URL, reqId, MESSAGE)

  elseif api_index == 3 then
    body = string.format([[{
      "msisdn":"%s",
      "cbUrl":"%s",
      "requestId":"%s"
    }]], msisdn, CALLBACK_URL, reqId)

  elseif api_index == 4 then
    body = string.format([[{
      "msisdn":"%s",
      "cbUrl":"%s",
      "templateID":"%s",
      "requestId":"%s"
    }]], msisdn, CALLBACK_URL, TEMPLATE_ID, reqId)
  end

  -- Rotate
  msisdn_index = msisdn_index + 1
  if msisdn_index > NUM_MSISDNS then
    msisdn_index = 1
    api_index = api_index + 1
    if api_index > 4 then api_index = 1 end
  end

  return wrk.format("POST", path, {
    ["Content-Type"] = "application/json",
    ["customerId"] = CUSTOMER_ID,
    ["Authorization"] = "Bearer " .. token
  }, body)
end

-- === RESPONSE ===
function response(status, headers, body)
  if body then local _ = body:sub(1, 1) end

  if not authenticated and status == 200 and body then
    token = body:match('"token"%s*:%s*"([^"]+)"')
    if token then
      authenticated = true
      token_fetched_at = os.time()
    end
  end

  local key = "status_" .. tostring(status)
  local count = wrk.thread:get(key) or 0
  wrk.thread:set(key, count + 1)
end

-- === DONE ===
function done(summary, latency, requests)
  local status_counts = {
    ["200"] = 0,
    ["400"] = 0,
    ["401"] = 0,
    ["403"] = 0,
    ["500"] = 0
  }
  local other = 0

  for _, thread in ipairs(threads) do
    for _, code in ipairs({"200", "400", "401", "403", "500"}) do
      local key = "status_" .. code
      local count = thread:get(key) or 0
      status_counts[code] = status_counts[code] + count
    end

    for i = 100, 599 do
      local code = tostring(i)
      if not status_counts[code] then
        local key = "status_" .. code
        local count = thread:get(key)
        if count then other = other + count end
      end
    end
  end

  print("------------------------------")
  print("๐Ÿ“Š Response Code Breakdown:")
  for _, code in ipairs({"200", "400", "401", "403", "500"}) do
    print(string.format("%s: %d", code, status_counts[code]))
  end
  print(string.format("Other: %d", other))
  print("๐Ÿ“ฆ Total requests: " .. summary.requests)
  print("------------------------------")
end