Skip to main content

Lua Scripting Guide

Drift testcases can be extended using Lua 5.4. This allows you to export functions to bind to testcase values or respond to lifecycle events with custom logic.

1. Script Structure​

Every Drift script must return a Lua Table containing event_handlers and exported_functions.

local function bearer_token(token)
return "12345678"
end

local exports = {
event_handlers = {
-- Respond to lifecycle events here
["operation:started"] = function(event, data)
print("Starting: " .. data[2]) -- Prints operation ID
end
},

exported_functions = {
-- Map Lua functions to names used in YAML
token = bearer_token
}
}

return exports

2. Event Handlers​

Events are strings structured with colons (e.g., namespace:event). You can use the * wildcard to match event patterns.

Wildcard Patterns​

  • *: Matches all events.
  • operation:*: Matches all events in the operation namespace (e.g., operation:started, operation:finished).
  • *:failed: Matches any event ending with failed (e.g., operation:failed).
  • Multiple namespaces are supported (e.g., xxx:yyy:zzz).

Core Framework Events​

EventTriggered When...
plugin:loadedA plugin is loaded.
plugin:unloadedA plugin is unloaded.
file:loadedA test file is loaded.
script:loadedA Lua script is loaded.
testcase:loadedA testcase file is loaded.
testcase:startedTestcase execution begins.
testcase:finishedTestcase execution completes.
operation:startedAn operation execution begins.
operation:preparedAn operation has been prepared and is ready for invocation.
operation:invokedAn operation has been invoked (request sent).
operation:passedOperation verification passes.
operation:failedOperation verification fails.
operation:finishedOperation verification is complete.
http:request(OAS Plugin) An HTTP request is created.

Event Data Modification​

Some events allow the event data to be modified. To modify event data, return the modified table from your event handler function. This modified data will then be merged into the event data before passing it to subsequent handlers.

For example, HTTP events allow you to modify headers or bodies before the request is sent:

["http:request"] = function(event, data)
data.headers["authorization"] = "bearer 12345678"
return data -- Return modified data
end

Note that most events are purely informationalβ€”returning modified data will only affect subsequent event handlers, not the original event.

3. Bound Functions​

Bound functions allow you to inject dynamic values into your yaml or validate expected values.

YAML Usage​

parameters:
authentication:
scheme: bearer
token: ${functions:token} # 'functions' is the namespace in sources

Function Signatures​

Exported functions are invoked with a single parameter:

  • Generation mode (parameter is nil): Return a generated value for the testcase to use.

Example: Simple Token Generation​

local function bearer_token(token)
if token then
-- Validation: Check if token is valid
if #token < 8 then
return error("Token too short")
end
else
-- Generation: Create a new token
return "12345678"
end
end

4. Lua Dependencies​

Importing Other Lua Scripts​

You can import other Lua scripts using standard Lua mechanisms, as long as they don't use native extensions:

local date = require "date"  -- Load another Lua module from the file system

LuaRocks Packages​

LuaRocks packages are supported, with the following requirements:

  • Only pure Lua packages are supported. Native C/FFI extensions cannot be used.
  • System-wide rocks should work without modification.
  • User-local rocks must be installed to the standard LuaRocks directory:
    • Unix-like systems: $HOME/.luarocks/share/lua/5.4

5. Provided Helper Functions​

Drift injects convenience functions directly into the Lua environment.

dbg(data)​

Returns a human-readable string representation of complex Lua Tables. Useful for debugging event data.

Example:

["operation:started"] = function(event, data)
print(dbg(data)) -- Pretty-prints the data structure
end

Output:

Table(
Integer(1) => String("Operation description"),
Integer(2) => String("operationId"),
Integer(3) => String("Test case title")
)

http(request_table)​

Executes synchronous HTTP requests. Essential because most Lua HTTP libraries use unsupported native extensions.

Request Fields:

FieldTypeDescription
urlStringRequest URL (required).
methodStringHTTP method. Defaults to GET if not provided.
queryString or TableQuery parameters. If a Table, entries are formatted as key=value and separated by &.
headersTableHTTP request headers.
bodyString or TableRequest body. If a Table, it will be rendered as JSON.

Response Fields:

FieldTypeDescription
statusIntegerHTTP response status code.
headersTableResponse headers.
bodyString or TableResponse body. JSON payloads are automatically parsed into Tables; other content types are returned as Strings.

Example:

local res = http({
url = "http://localhost:8080/api/users",
method = "POST",
headers = {
["Content-Type"] = "application/json",
["Authorization"] = "Bearer token123"
},
body = { name = "John", email = "john@example.com" }
})

if res.status == 201 then
print("User created: " .. res.body.id)
else
print("Error: " .. res.status)
end

6. Script Requirements & Limitations​

Lua Engine​

  • Embedded Lua 5.4 VM.

Capabilities​

Scripts have access to:

  • OS environment (via standard Lua os module)
  • File system (via standard Lua io module)
  • Networking (via the provided http() function and other Lua networking libraries)
  • Using other Lua scripts (via require() for pure Lua modules)
  • LuaRocks packages (as long as they are pure Lua)

Restrictions​

  • No C/FFI extensions are supported. This means:
    • Native Lua extensions cannot be used
    • LuaRocks packages must be pure Lua only
  • Pure Lua LuaRocks packages can be used if installed to the standard location:
    • Unix-like systems: $HOME/.luarocks/share/lua/5.4