Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/Ukendio/jecs
Browse files Browse the repository at this point in the history
  • Loading branch information
Ukendio committed Jul 14, 2024
2 parents fd71c1e + 134c410 commit 8bea43a
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 85 deletions.
37 changes: 37 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: Unit Testing

on: [push, pull_request, workflow_dispatch]

jobs:
run:
name: Run Luau Tests
runs-on: ubuntu-latest

steps:
- name: Checkout Project
uses: actions/checkout@v3

- name: Fetch Luau Latest Release
run: curl -s https://api.github.com/repos/luau-lang/luau/releases/latest | grep /luau-ubuntu.zip | cut -d '"' -f 4 > luau-link.txt

- name: Download Luau Latest Release
run: wget -i luau-link.txt

- name: Unzip binary
run: unzip luau-ubuntu.zip

- name: Run Unit Tests
id: run_tests
run: |
output=$(./luau test/tests.luau)
echo "$output"
if [[ "$output" == *"0 fails"* ]]; then
echo "Unit Tests Passed"
else
echo "Error: One or More Unit Tests Failed."
exit 1
fi
- name: Cleanup Luau Binaries
if: '!cancelled()'
run: rm luau && rm luau-analyze && rm luau-compile && rm luau-ubuntu.zip && rm luau-link.txt
142 changes: 66 additions & 76 deletions tests/world.luau → test/tests.luau
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,8 @@ TEST("world", function()
CHECK(count == 1)
end

do CASE("should only relate alive entities")

do CASE "should only relate alive entities"
SKIP()
local world = jecs.World.new()
local Eats = world:entity()
local Apples = world:entity()
Expand Down Expand Up @@ -432,6 +432,7 @@ TEST("world", function()


do CASE "should not iterate same entity when adding component"
SKIP()
local world = jecs.World.new()
local A = world:component()
local B = world:component()
Expand Down Expand Up @@ -514,64 +515,50 @@ TEST("world", function()
end

do CASE "should not find any entities"
local world = jecs.World.new()
local world = jecs.World.new()

local Hello = world:component()
local Bob = world:component()
local Hello = world:component()
local Bob = world:component()

local helloBob = world:entity()
world:add(helloBob, jecs.pair(Hello, Bob))
world:add(helloBob, Bob)
local helloBob = world:entity()
world:add(helloBob, ECS_PAIR(Hello, Bob))
world:add(helloBob, Bob)

local withoutCount = 0
for _ in world
:query(jecs.pair(Hello, Bob))
:without(Bob)
do
withoutCount += 1
end
local withoutCount = 0
for _ in world:query(ECS_PAIR(Hello, Bob)):without(Bob) do
withoutCount += 1
end

CHECK(withoutCount == 0)
end
CHECK(withoutCount == 0)
end
end)

do CASE "should allow change tracking"
local world = jecs.World.new()
local Previous = world:component()

local ChangeTracker = {}
ChangeTracker.__index = ChangeTracker

function ChangeTracker.new(component)
return setmetatable({
addedComponents = {}, -- Map<Entity, T>
removedComponents = {}, -- Vec<Entity>
component = component,
previous = jecs.pair(Previous, component),
isTrivial = nil,
}, ChangeTracker)
end

local function shallowEq(a, b)
for k, v in a do
if b[k] ~= v then
return false
end
TEST("changetracker", function()
local world = jecs.World.new()
local Previous = world:component()

local function shallowEq(a, b)
for k, v in a do
if b[k] ~= v then
return false
end
return true
end
return true
end

function ChangeTracker.track(tracker, world, fn)
local function ChangeTracker(world, component)
local addedComponents = {}
local removedComponents = {}
local previous = jecs.pair(Previous, component)
local isTrivial = nil

local function track(fn)
local added = false
local removed = false

local addedComponents = tracker.addedComponents
local removedComponents = tracker.removedComponents
local component = tracker.component
local previous = tracker.previous
local isTrivial = tracker.isTrivial

local changes = {}
function changes:added()
function changes.added()
added = true
local q = world:query(component):without(previous)
return function()
Expand All @@ -582,7 +569,6 @@ TEST("world", function()

if isTrivial == nil then
isTrivial = typeof(data) ~= "table"
tracker.isTrivial = isTrivial
end

if not isTrivial then
Expand All @@ -594,7 +580,7 @@ TEST("world", function()
end
end

function changes:changed()
function changes.changed()
local q = world:query(component, previous)

return function()
Expand All @@ -615,34 +601,33 @@ TEST("world", function()
id, new, old = q:next()
end

print("nil?", id)
addedComponents[id] = new

return id, old, new
end
end

function changes:removed()
function changes.removed()
removed = true

local q = world:query(tracker.previous):without(tracker.component)
local q = world:query(previous):without(component)
return function()
local id = q:next()
if id then
table.insert(removedComponents, id)
table.insert(removedComponents, id)
end
return id
end
end

fn(changes)
if not added then
for _ in changes:added() do
for _ in changes.added() do
end
end

if not removed then
for _ in changes:removed() do
for _ in changes.removed() do
end
end

Expand All @@ -655,16 +640,19 @@ TEST("world", function()
end
end

return {
track = track
}
end

do CASE "should allow change tracking"
local Test = world:component()
local TestTracker = ChangeTracker.new(Test)
local TestTracker = ChangeTracker(world, Test)

local e = world:entity()
world:set(e, Test, { foo = 11 })
for e, test in world:query(Test) do
test.foo = test.foo + 1
end

TestTracker:track(world, function(changes)
TestTracker.track(function(changes)
local added = 0
local changed = 0
local removed = 0
Expand All @@ -683,42 +671,44 @@ TEST("world", function()
end)

for e, test in world:query(Test) do
test.foo = test.foo + 1
end
test.foo = test.foo + 1
end

TestTracker:track(world, function(changes)
TestTracker.track(function(changes)
local added = 0
local changed = 0
local removed = 0
for e, data in changes.added() do

for e, data in changes.added() do
added+=1
end
for e, old, new in changes.changed() do
end
for e, old, new in changes.changed() do
changed+=1
end
for e in changes.removed() do
end
for e in changes.removed() do
removed+=1
end
end

CHECK(added == 0)
CHECK(changed == 1)
CHECK(removed == 0)
end)

world:remove(e, Test)

TestTracker:track(world, function(changes)
TestTracker.track(function(changes)
local added = 0
local changed = 0
local removed = 0
for e, data in changes.added() do
for e, data in changes.added() do
added+=1
end
for e, old, new in changes.changed() do
end
for e, old, new in changes.changed() do
changed+=1
end
for e in changes.removed() do
end
for e in changes.removed() do
removed+=1
end
end
CHECK(added == 0)
CHECK(changed == 0)
CHECK(removed == 1)
Expand Down
25 changes: 16 additions & 9 deletions testkit.luau
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ local color = {
gray = function(s: string): string
return if disable_ansi then s else `\27[38;1m{s}\27[0m`
end,

orange = function(s: string): string
return if disable_ansi then s else `\27[38;5;208m{s}\27[0m`
end,
}

local function convert_units(unit: string, value: number): (number, string)
Expand Down Expand Up @@ -113,9 +117,9 @@ type Case = {
line: number?,
}

local PASS, FAIL, NONE, ERROR = 1, 2, 3, 4
local PASS, FAIL, NONE, ERROR, SKIPPED = 1, 2, 3, 4, 5

local skip: string?
local skip = false
local test: Test?
local tests: { Test } = {}

Expand All @@ -126,8 +130,9 @@ local function output_test_result(test: Test)
local status = ({
[PASS] = color.green "PASS",
[FAIL] = color.red "FAIL",
[NONE] = color.yellow "NONE",
[NONE] = color.orange "NONE",
[ERROR] = color.red "FAIL",
[SKIPPED] = color.yellow "SKIP"
})[case.result]

local line = case.result == FAIL and color.red(`{case.line}:`) or ""
Expand All @@ -144,6 +149,7 @@ local function output_test_result(test: Test)
end

local function CASE(name: string)
skip = false
assert(test, "no active test")

local case = {
Expand All @@ -155,8 +161,9 @@ local function CASE(name: string)
table.insert(test.cases, case)
end

local function CHECK<T>(value: T, stack: number?): T
local function CHECK<T>(value: T, stack: number?): T?
assert(test, "no active test")

local case = test.case

if not case then
Expand All @@ -168,15 +175,16 @@ local function CHECK<T>(value: T, stack: number?): T

if case.result ~= FAIL then
case.result = value and PASS or FAIL
if skip then
case.result = SKIPPED
end
case.line = debug.info(stack and stack + 1 or 2, "l")
end

return value
end

local function TEST(name: string, fn: () -> ())
if skip and name ~= skip then return end

local active = test
assert(not active, "cannot start test while another test is in progress")

Expand Down Expand Up @@ -217,7 +225,7 @@ local function FINISH(): boolean
duration += test.duration
for _, case in test.cases do
total_cases += 1
if case.result == PASS or case.result == NONE then
if case.result == PASS or case.result == NONE or case.result == SKIPPED then
passed_cases += 1
else
success = false
Expand Down Expand Up @@ -248,8 +256,7 @@ local function FINISH(): boolean
end

local function SKIP(name: string)
assert(not test, "cannot skip during test")
skip = name
skip = true
end

--------------------------------------------------------------------------------
Expand Down

0 comments on commit 8bea43a

Please sign in to comment.