From 47e632254f2829886b3797ad5bfb708723b0d1ba Mon Sep 17 00:00:00 2001 From: a Date: Sun, 6 Jul 2025 16:40:46 -0500 Subject: [PATCH] noot --- Makefile | 5 +- src/git.lua | 1 + test.lua | 111 +++++++++++++++++++++++++++++++++++++++ test/test_git_parser.lua | 99 ++++++++++++++++++++++++++++++++++ 4 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 test.lua create mode 100644 test/test_git_parser.lua diff --git a/Makefile b/Makefile index 90c6ad8..996eb45 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: all install +.PHONY: all install test SOURCES_SRC:=$(shell find src -type f ) LIBS_SRC:=$(shell find lib -type f ) @@ -18,3 +18,6 @@ dist/repotool: $(SOURCES_SRC) $(LIBS_SRC) main.lua luabundler bundle main.lua -p "./src/?.lua" -p "./lib/?.lua" -o dist/repotool @sed -i "1i#!/usr/bin/env luajit" "dist/repotool" chmod +x dist/repotool + +test: + @lua test.lua diff --git a/src/git.lua b/src/git.lua index 61d881a..3cfa676 100644 --- a/src/git.lua +++ b/src/git.lua @@ -28,6 +28,7 @@ function git.parse_url(url) if not domain then domain, path = url:match("^[^@]+@([^:]+):(.+)$") end + -- SSH URLs (ssh://...) if not domain then domain, path = url:match("^ssh://[^@]*@?([^/]+)/(.+)%.git$") end diff --git a/test.lua b/test.lua new file mode 100644 index 0000000..80ee8c2 --- /dev/null +++ b/test.lua @@ -0,0 +1,111 @@ +#!/usr/bin/env lua + +-- Test runner for repotool +-- This script discovers and runs all test files in the test/ directory + +-- Add src to package path +package.path = package.path .. ";./src/?.lua" + +-- ANSI color codes +local colors = { + green = "\27[32m", + red = "\27[31m", + yellow = "\27[33m", + reset = "\27[0m" +} + +-- Test statistics +local stats = { + total = 0, + passed = 0, + failed = 0, + errors = {} +} + +-- Simple test framework +_G.test = {} +_G.test.current_suite = nil +_G.test.current_test = nil + +function _G.test.suite(name, fn) + _G.test.current_suite = name + print("\n" .. colors.yellow .. "Testing " .. name .. colors.reset) + fn() + _G.test.current_suite = nil +end + +function _G.test.case(name, fn) + _G.test.current_test = name + stats.total = stats.total + 1 + + local status, err = pcall(fn) + if status then + stats.passed = stats.passed + 1 + print(" " .. colors.green .. "✓" .. colors.reset .. " " .. name) + else + stats.failed = stats.failed + 1 + print(" " .. colors.red .. "✗" .. colors.reset .. " " .. name) + table.insert(stats.errors, { + suite = _G.test.current_suite, + test = name, + error = err + }) + end + + _G.test.current_test = nil +end + +function _G.assert_eq(actual, expected, message) + if actual ~= expected then + error((message or "Assertion failed") .. "\n Expected: " .. tostring(expected) .. "\n Actual: " .. tostring(actual)) + end +end + +function _G.assert_nil(value, message) + if value ~= nil then + error((message or "Expected nil") .. "\n Got: " .. tostring(value)) + end +end + +function _G.assert_not_nil(value, message) + if value == nil then + error(message or "Expected non-nil value") + end +end + +-- Discover and run test files +local function run_tests() + local handle = io.popen("find test -name '*.lua' -type f | sort") + local test_files = handle:read("*a") + handle:close() + + for file in test_files:gmatch("[^\n]+") do + -- Skip the test.lua file itself + if not file:match("test%.lua$") then + dofile(file) + end + end +end + +-- Main +print(colors.yellow .. "Running repotool tests..." .. colors.reset) +run_tests() + +-- Print summary +print("\n" .. string.rep("-", 40)) +print("Test Summary:") +print(" Total: " .. stats.total) +print(" " .. colors.green .. "Passed: " .. stats.passed .. colors.reset) +print(" " .. colors.red .. "Failed: " .. stats.failed .. colors.reset) + +-- Print errors if any +if #stats.errors > 0 then + print("\n" .. colors.red .. "Failures:" .. colors.reset) + for _, err in ipairs(stats.errors) do + print("\n " .. err.suite .. " > " .. err.test) + print(" " .. err.error:gsub("\n", "\n ")) + end +end + +-- Exit with appropriate code +os.exit(stats.failed > 0 and 1 or 0) \ No newline at end of file diff --git a/test/test_git_parser.lua b/test/test_git_parser.lua new file mode 100644 index 0000000..87d8c52 --- /dev/null +++ b/test/test_git_parser.lua @@ -0,0 +1,99 @@ +local git = require("git") + +test.suite("git.parse_url", function() + test.case("parses HTTPS URL without .git", function() + local domain, path = git.parse_url("https://gitlab.freedesktop.org/xorg/proto") + assert_eq(domain, "gitlab.freedesktop.org", "Domain should be gitlab.freedesktop.org") + assert_eq(path, "xorg/proto", "Path should be xorg/proto") + end) + + test.case("parses HTTPS URL without .git", function() + local domain, path = git.parse_url("https://gitlab.freedesktop.org/xorg/proto/xcbproto") + assert_eq(domain, "gitlab.freedesktop.org", "Domain should be gitlab.freedesktop.org") + assert_eq(path, "xorg/proto/xcbproto", "Path should be xorg/proto/xcbproto") + end) + + test.case("parses HTTPS URL with .git", function() + local domain, path = git.parse_url("https://github.com/user/repo.git") + assert_eq(domain, "github.com", "Domain should be github.com") + assert_eq(path, "user/repo", "Path should be user/repo") + end) + + test.case("parses HTTPS URL with authentication", function() + local domain, path = git.parse_url("https://user@gitlab.freedesktop.org/xorg/proto") + assert_eq(domain, "gitlab.freedesktop.org", "Domain should be gitlab.freedesktop.org") + assert_eq(path, "xorg/proto", "Path should be xorg/proto") + end) + + test.case("parses HTTPS URL with authentication and .git", function() + local domain, path = git.parse_url("https://user:token@github.com/user/repo.git") + assert_eq(domain, "github.com", "Domain should be github.com") + assert_eq(path, "user/repo", "Path should be user/repo") + end) + + test.case("parses SSH URL", function() + local domain, path = git.parse_url("git@github.com:user/repo.git") + assert_eq(domain, "github.com", "Domain should be github.com") + assert_eq(path, "user/repo", "Path should be user/repo") + end) + + test.case("parses SSH URL without .git", function() + local domain, path = git.parse_url("git@gitlab.com:group/project") + assert_eq(domain, "gitlab.com", "Domain should be gitlab.com") + assert_eq(path, "group/project", "Path should be group/project") + end) + + test.case("parses SSH URL with port", function() + local domain, path = git.parse_url("ssh://git@github.com/user/repo.git") + assert_eq(domain, "github.com", "Domain should be github.com") + assert_eq(path, "user/repo", "Path should be user/repo") + end) + + test.case("parses bare domain path", function() + local domain, path = git.parse_url("gfx.cafe/oku/trade") + assert_eq(domain, "gfx.cafe", "Domain should be gfx.cafe") + assert_eq(path, "oku/trade", "Path should be oku/trade") + end) + + test.case("returns nil for invalid URLs", function() + local domain, path = git.parse_url("not-a-url") + assert_nil(domain, "Domain should be nil for invalid URL") + assert_nil(path, "Path should be nil for invalid URL") + end) + + test.case("handles complex paths", function() + local domain, path = git.parse_url("https://gitlab.com/group/subgroup/project.git") + assert_eq(domain, "gitlab.com", "Domain should be gitlab.com") + assert_eq(path, "group/subgroup/project", "Path should preserve subgroups") + end) + + test.case("does not parse short SSH syntax as regular domain", function() + -- This ensures git@g:xorg/proto is treated as SSH, not misinterpreted + local domain, path = git.parse_url("git@g:xorg/proto") + assert_eq(domain, "g", "Domain should be g for SSH URL") + assert_eq(path, "xorg/proto", "Path should be xorg/proto") + end) +end) + +test.suite("git.valid_url", function() + test.case("identifies HTTPS URLs", function() + assert_eq(git.valid_url("https://github.com/user/repo"), 1) + assert_eq(git.valid_url("http://example.com/path"), 1) + end) + + test.case("identifies SSH URLs", function() + assert_eq(git.valid_url("git@github.com:user/repo"), 2) + assert_eq(git.valid_url("ssh://git@github.com/user/repo"), 2) + end) + + test.case("identifies bare domain paths", function() + assert_eq(git.valid_url("example.com/user/repo"), 3) + assert_eq(git.valid_url("sub.example.org/path/to/repo"), 3) + end) + + test.case("returns -1 for invalid URLs", function() + assert_eq(git.valid_url("not-a-url"), -1) + assert_eq(git.valid_url("/local/path"), -1) + assert_eq(git.valid_url("file:///path"), -1) + end) +end)