Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions .github/schemas/sharingoptions-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://beyondallreason.info/schemas/sharingoptions.json",
"title": "Sharing Options Configuration Schema",
"description": "Schema for validating sharing mode configurations in Beyond All Reason",
"type": "object",
"required": ["version", "modes"],
"properties": {
"version": {
"type": "integer",
"minimum": 1,
"description": "Schema version for compatibility tracking"
},
"modes": {
"type": "array",
"minItems": 1,
"description": "Array of sharing modes",
"items": {
"type": "object",
"required": ["key", "name", "desc"],
"properties": {
"key": {
"type": "string",
"pattern": "^[a-z_][a-z0-9_]*$",
"description": "Unique identifier for the mode (snake_case)"
},
"name": {
"type": "string",
"minLength": 1,
"maxLength": 50,
"description": "Display name for the mode"
},
"desc": {
"type": "string",
"minLength": 1,
"maxLength": 200,
"description": "Description of what this mode does"
},
"allowRanked": {
"type": "boolean",
"default": true,
"description": "Whether this mode allows ranked games"
},
"options": {
"type": "object",
"description": "Modoption overrides for this mode",
"patternProperties": {
"^[a-z_][a-z0-9_]*$": {
"type": "object",
"properties": {
"value": {
"oneOf": [
{"type": "string"},
{"type": "number"},
{"type": "boolean"}
],
"description": "Value to set for this option"
},
"locked": {
"type": "boolean",
"default": false,
"description": "Whether this option should be read-only"
},
"ui": {
"type": "string",
"enum": ["visible", "hidden"],
"description": "UI visibility for this option"
},
"bounds": {
"type": "object",
"description": "Mode-specific bounds that must be within global modoption bounds",
"properties": {
"min": {
"type": "number",
"description": "Minimum value (for number options)"
},
"max": {
"type": "number",
"description": "Maximum value (for number options)"
},
"step": {
"type": "number",
"minimum": 0,
"description": "Step size (for number options)"
},
"items": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"description": "Allowed items subset (for list options)"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
}
48 changes: 48 additions & 0 deletions .github/workflows/validate-sharingoptions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Validate Sharing Options

on:
pull_request:
paths:
- 'gamedata/sharingoptions.json'
- '.github/schemas/sharingoptions-schema.json'
push:
branches: [ master, develop ]
paths:
- 'gamedata/sharingoptions.json'
- '.github/schemas/sharingoptions-schema.json'

jobs:
validate-schema:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install AJV CLI
run: npm install -g ajv-cli

- name: Validate sharing options against schema
run: |
if [ -f "gamedata/sharingoptions.json" ]; then
ajv validate -s .github/schemas/sharingoptions-schema.json -d gamedata/sharingoptions.json
echo "✅ Sharing options JSON is valid"
else
echo "⚠️ No sharingoptions.json found, skipping validation"
fi

- name: Validate mode keys are unique
run: |
if [ -f "gamedata/sharingoptions.json" ]; then
# Check for duplicate mode keys
keys=$(jq -r '.modes[].key' gamedata/sharingoptions.json | sort)
duplicates=$(echo "$keys" | uniq -d)
if [ -n "$duplicates" ]; then
echo "❌ Duplicate mode keys found: $duplicates"
exit 1
fi
echo "✅ All mode keys are unique"
fi
33 changes: 31 additions & 2 deletions .luarc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,41 @@
},
"workspace": {
"library": [
"recoil-lua-library"
"recoil-lua-library",
"luarules/",
"luaui/"
],
"userThirdParty": [
"types"
],
"ignoreDir": [
".vscode",
"luaui/Tests",
"luaui/TestsExamples"
]
],
"checkThirdParty": false
},
"diagnostics": {
"globals": [
"VFS",
"Spring",
"Game",
"CMD",
"gadget",
"widget",
"GG",
"WG",
"gadgetHandler",
"widgetHandler"
],
"type": {
"definition": [
"luaui/types/"
]
},
"workspaceDelay": 0
},
"semantic": {
"enable": true
}
}
103 changes: 103 additions & 0 deletions README_test_runner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# BAR Standalone Test Runner

A command-line test runner for BAR's unit tests that can execute tests without starting the game or Spring engine.

## Installation

Ensure you have Lua 5.1 installed:
```bash
sudo apt install lua5.1
```

## Usage

Run the test runner from the BAR repository root directory:

```bash
# Run all unit tests
lua5.1 test_runner.lua

# Run all unit tests (explicit pattern)
lua5.1 test_runner.lua unit/

# Run specific test file
lua5.1 test_runner.lua unit/test_policy_builder
lua5.1 test_runner.lua unit/test_predicates
lua5.1 test_runner.lua unit/test_resource_tax_calculations
lua5.1 test_runner.lua unit/test_unit_sharing_logic
lua5.1 test_runner.lua test_ally_assist

# Run tests matching a pattern
lua5.1 test_runner.lua predicates
lua5.1 test_runner.lua policy
```

## Features

- **Standalone Execution**: No need to start BAR or Spring engine
- **Fast Feedback**: Quick test execution for tight development loops
- **Colored Output**: Green for pass, red for fail, magenta for errors
- **Timing Information**: Shows execution time for each test
- **Pattern Matching**: Run specific tests or test groups
- **Exit Codes**: Returns 0 for success, 1 for failures (CI-friendly)

## Test Structure

Unit tests are located in `luaui/Tests/team_transfer/unit/` and follow this structure:

```lua
function setup()
-- Test setup code (mocking, initialization)
end

function cleanup()
-- Test cleanup code
end

function test()
-- Test assertions and logic
end
```

## Mocking

The test runner provides mocking capabilities through BAR's testing utilities:

- `Test.mock(parent, target, fn)` - Mock a function
- `Test.spy(parent, target)` - Spy on function calls
- `VFS.Include(path)` - Mock VFS system for loading modules

## Output Example

```
BAR Standalone Test Runner
==========================
PASS: test_policy_builder.lua [2 ms]
PASS: test_predicates.lua [1 ms]
PASS: test_resource_tax_calculations.lua [3 ms]
PASS: test_unit_sharing_logic.lua [2 ms]
PASS: test_ally_assist.lua [1 ms]

Results: 6/6 tests passed
All tests passed! ✓
```

## Integration with CI

The test runner returns appropriate exit codes for CI integration:
- Exit code 0: All tests passed
- Exit code 1: One or more tests failed

## Troubleshooting

### "lua: command not found"
Install Lua 5.1: `sudo apt install lua5.1`

### "Could not open file"
Ensure you're running the command from the BAR repository root directory.

### Test failures
Check the error messages in the output. Common issues:
- Missing mock setup in test files
- Incorrect assertions
- Missing dependencies in test environment
Loading