Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6b2d800
Add CodeQL analysis workflow configuration (#163)
welcor Apr 18, 2026
ce423e9
Fix for code scanning alert no. 74: Potential use after free (#164)
welcor Apr 18, 2026
28622d9
Add initialization and build instructions to AGENTS.md (#166)
welcor Apr 19, 2026
8548bbe
Fix questmaster holding items: extract object after AQ_OBJ_RETURN que…
Copilot Apr 19, 2026
862c887
Better naming in do_drink. An unlimited source is never empty. (#167)
welcor Apr 21, 2026
039e45c
Potential fix for code scanning alert no. 2: Redundant null check due…
welcor Apr 21, 2026
1dfbe0f
Potential fix for code scanning alert no. 3: Redundant null check due…
welcor Apr 21, 2026
dbd6bfc
Potential fix for code scanning alert no. 4: Redundant null check due…
welcor Apr 21, 2026
171381f
Potential fix for code scanning alert no. 5: Redundant null check due…
welcor Apr 21, 2026
b9f4947
Potential fix for code scanning alert no. 1: Workflow does not contai…
welcor Apr 21, 2026
a465860
Potential fix for code scanning alert no. 70: Incorrect return-value …
welcor Apr 21, 2026
d4089c5
Potential fix for code scanning alert no. 73: Potential use after fre…
welcor Apr 21, 2026
1025181
Potential fix for code scanning alert no. 55: Call to alloca in a loo…
welcor Apr 21, 2026
552461d
Fix all compiler warnings in build output (#176)
Copilot Apr 21, 2026
ac94839
Add Unity-based unit test infrastructure (Phase 1 — 117 tests) (#177)
Copilot Apr 22, 2026
87c75da
Improve error message detail for wdoor/mdoor/odoor invalid args (#178)
Copilot Apr 23, 2026
af06fa0
Fix stack buffer overflow in perform_complex_alias() via unbounded al…
Copilot Apr 25, 2026
a049fdd
Fix stray null write from sizeof(pointer) bug in var_subst() (#190)
Copilot Apr 25, 2026
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
20 changes: 18 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ name: C/C++ CI
on:
push:
branches: [ "master" ]
pull_request:
pull_request_target:
branches: [ "master" ]

permissions:
contents: read
checks: write
pull-requests: write

jobs:
build:

Expand All @@ -16,4 +21,15 @@ jobs:
- name: configure
run: ./configure
- name: build
run: cd src && touch .accepted && make
working-directory: src
run: touch .accepted && make
- name: test
working-directory: tests
run: make test
- name: publish test results
uses: dorny/test-reporter@v1
if: always()
with:
name: Unity Tests
path: tests/test-results/*.xml
reporter: java-junit
96 changes: 96 additions & 0 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL Advanced"

on:
push:
branches: [ "master" ]
schedule:
- cron: '42 10 * * 4'

jobs:
analyze:
name: Analyze (${{ matrix.language }})
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners (GitHub.com only)
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
permissions:
# required for all workflows
security-events: write

# required to fetch internal or private CodeQL packs
packages: read

# only required for workflows in private repositories
actions: read
contents: read

strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
- language: c-cpp
build-mode: manual
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
# Use `c-cpp` to analyze code written in C, C++ or both
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- name: Checkout repository
uses: actions/checkout@v4

# Add any setup steps before running the `github/codeql-action/init` action.
# This includes steps like installing compilers or runtimes (`actions/setup-node`
# or others). This is typically only required for manual builds.
# - name: Setup runtime (example)
# uses: actions/setup-example@v1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}

# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.

# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality

# If the analyze step fails for one of the languages you are analyzing with
# "We were unable to automatically build your code", modify the matrix above
# to set the build mode to "manual" for that language. Then modify this step
# to build your code.
# ℹ️ Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
- name: Run manual build steps
if: matrix.build-mode == 'manual'
shell: bash
run: |
./configure
cd src && touch .accepted && make
exit

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ config.status
src/Makefile
src/conf.h
src/util/Makefile
tests/Makefile
src/.accepted
src/depend
src/util/depend
Expand Down Expand Up @@ -93,3 +94,10 @@ src/test/testfile
.Trashes
ehthumbs.db
Thumbs.db

# Unit test binaries (built artifacts)
tests/test_utils
tests/test_random
tests/test_interpreter
tests/test_class
tests/test-results/
14 changes: 14 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# To initialize the repository:

Run these commands from the project directory.

```shell
./configure && touch src/.accepted # the src/.accepted file must exist to build.
```

# To build the code:

```shell
cd src # make must be run from the src dir
make # builds all changed source files.
```
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ add_executable(circle ${SRC_FILES})
target_link_libraries(circle ${EXTRA_LIBS})

add_subdirectory(src/util)
add_subdirectory(tests)

if (MEMORY_DEBUG)
message(STATUS "MEMORY_DEBUG is activated, setting up zmalloc")
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
Files for tbaMUD.

## Unit Tests

tbaMUD ships with a C unit-test suite located in the `tests/` directory.
The suite uses the [Unity](https://github.com/ThrowTheSwitch/Unity) test
framework (vendored under `tests/vendor/unity/`).

### Quick start

```
./configure
cd tests && make test
```

`make test` builds each test binary, runs it, and writes JUnit XML results to
`tests/test-results/`. A summary is printed to the terminal:

```
[PASS] test_utils
[PASS] test_random
[PASS] test_interpreter
[PASS] test_class
```

### CI

The GitHub Actions workflow (`.github/workflows/build.yml`) runs `make test`
on every push and pull request against `master` and publishes a formatted
report via the `dorny/test-reporter` action.

See [doc/testing.md](doc/testing.md) for full details on adding new tests and
understanding the test infrastructure.

2 changes: 1 addition & 1 deletion cnf/configure.in
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,6 @@ AC_CHECK_PROTO(unlink)
AC_CHECK_PROTO(vsnprintf)
AC_CHECK_PROTO(write)

AC_OUTPUT(src/Makefile src/util/Makefile)
AC_OUTPUT(src/Makefile src/util/Makefile tests/Makefile)
#
echo "Configuration completed. To compile, type: cd src; make"
2 changes: 1 addition & 1 deletion configure
Original file line number Diff line number Diff line change
Expand Up @@ -5711,7 +5711,7 @@ EOF

cat >> $CONFIG_STATUS <<EOF

CONFIG_FILES=\${CONFIG_FILES-"src/Makefile src/util/Makefile"}
CONFIG_FILES=\${CONFIG_FILES-"src/Makefile src/util/Makefile tests/Makefile"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
Expand Down
150 changes: 150 additions & 0 deletions doc/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# tbaMUD Unit Testing

_Updated 2026-04_

## Overview

tbaMUD has a C unit-test suite built on the
[Unity](https://github.com/ThrowTheSwitch/Unity) framework. Tests live in the
`tests/` directory alongside the vendored Unity source.

```
tests/
Makefile.in – Autoconf template; processed by configure
test_stubs.c – Weak-symbol stubs that satisfy mud headers
unity_to_junit.py – Converts Unity output to JUnit XML
test_class.c – Tests for src/class.c
test_interpreter.c – Tests for src/interpreter.c
test_random.c – Tests for src/random.c
test_utils.c – Tests for src/utils.c
vendor/unity/ – Vendored Unity test framework
```

## Prerequisites

| Requirement | Notes |
|---|---|
| C compiler (gcc or clang) | Same compiler used to build the mud |
| GNU make | Any POSIX-compatible make works |
| Python 3 | Required only for JUnit XML conversion (`unity_to_junit.py`) |
| autoconf / configure | Already needed to build the mud |

## Running the tests

Run `./configure` from the repository root first (only needed once):

```sh
./configure
```

Then build and run all tests from the `tests/` directory:

```sh
cd tests
make test
```

`make test` performs the following steps for each test binary:

1. Compiles the test binary (if not already up to date).
2. Runs the binary and captures stdout/stderr to `test-results/<name>.out`.
3. Measures wall-clock elapsed time.
4. Converts the Unity output to JUnit XML via `unity_to_junit.py`, writing
`test-results/<name>.xml`.
5. Prints `[PASS] <name>` or `[FAIL] <name>` and exits non-zero if any
binary failed.

To build the test binaries without running them:

```sh
cd tests
make
```

To remove all test binaries and result files:

```sh
cd tests
make clean
```

## Test suites

| Binary | Source under test | Test file |
|---|---|---|
| `test_utils` | `src/utils.c`, `src/random.c` | `test_utils.c` |
| `test_random` | `src/random.c`, `rand_number`/`dice` in `src/utils.c` | `test_random.c` |
| `test_interpreter` | `src/interpreter.c` | `test_interpreter.c` |
| `test_class` | `src/class.c` | `test_class.c` |

## Writing a new test

### Adding a test case to an existing suite

1. Open the relevant `test_<name>.c` file.
2. Write a function with the signature `void test_my_feature(void)`.
3. Use Unity assertion macros such as `TEST_ASSERT_EQUAL_INT`,
`TEST_ASSERT_NULL`, `TEST_ASSERT_TRUE`, etc.
4. Register the function in the `main()` block:
```c
RUN_TEST(test_my_feature);
```

Example:

```c
void test_str_cmp_equal_strings(void)
{
TEST_ASSERT_EQUAL_INT(0, str_cmp("hello", "hello"));
}
```

### Creating a new test suite

1. Create `tests/test_<module>.c`. Copy the boilerplate from an existing
suite: include `unity.h`, define `setUp`/`tearDown` (may be empty), write
test functions, and provide a `main()` that calls `UNITY_BEGIN()`,
`RUN_TEST(...)` for each function, and `return UNITY_END();`.

2. Add the binary to `tests/Makefile.in`:
- Add the name to the `TESTS` variable.
- Add a build rule:
```make
test_<module>: $(UNITY_SRC) $(STUBS_SRC) $(UTILS_SRC) \
$(SRCDIR)/<module>.c test_<module>.c
$(COMPILE) -o $@ $^ $(LIBS)
```

3. Re-run `./configure` from the repository root to regenerate
`tests/Makefile` from the updated `tests/Makefile.in`.

### Stubs

Many mud source files reference global variables and functions that are only
meaningful at runtime (e.g. `descriptor_list`, `log()`). `test_stubs.c`
provides zero-initialised definitions and `__attribute__((weak))` stub
implementations for these symbols so that test binaries link without pulling
in the full mud.

If a new test requires a function not yet stubbed, add a weak stub to
`test_stubs.c`:

```c
__attribute__((weak)) void my_function(void) { /* no-op */ }
```

## JUnit XML output and CI

`unity_to_junit.py` reads Unity's line-oriented output on stdin and writes a
JUnit-compatible XML file. It accepts an optional third argument with the
elapsed wall-clock time in seconds (provided by the `make test` target):

```
usage: unity_to_junit.py <suite_name> <output.xml> [elapsed_seconds]
```

The GitHub Actions workflow (`.github/workflows/build.yml`) runs `make test`
on every push and pull request against `master`. After the tests finish the
`dorny/test-reporter` action reads `tests/test-results/*.xml` and publishes a
formatted report as a GitHub Check with pass/fail counts and per-suite
execution times.
Loading
Loading