start testing
This commit is contained in:
281
testing/__tests__/path_validation_test.lua
Normal file
281
testing/__tests__/path_validation_test.lua
Normal file
@@ -0,0 +1,281 @@
|
||||
-- Test suite for path validation functions
|
||||
-- Tests sanitizePath, isPathSafe, validatePath, getFileExtension, hasAllowedExtension
|
||||
|
||||
package.path = package.path .. ";./?.lua;./modules/?.lua"
|
||||
|
||||
-- Load love stub before anything else
|
||||
require("testing.loveStub")
|
||||
|
||||
local luaunit = require("testing.luaunit")
|
||||
local utils = require("modules.utils")
|
||||
|
||||
-- Test suite for sanitizePath
|
||||
TestSanitizePath = {}
|
||||
|
||||
function TestSanitizePath:testSanitizePath_NilInput()
|
||||
local result = utils.sanitizePath(nil)
|
||||
luaunit.assertEquals(result, "")
|
||||
end
|
||||
|
||||
function TestSanitizePath:testSanitizePath_EmptyString()
|
||||
local result = utils.sanitizePath("")
|
||||
luaunit.assertEquals(result, "")
|
||||
end
|
||||
|
||||
function TestSanitizePath:testSanitizePath_Whitespace()
|
||||
local result = utils.sanitizePath(" /path/to/file ")
|
||||
luaunit.assertEquals(result, "/path/to/file")
|
||||
end
|
||||
|
||||
function TestSanitizePath:testSanitizePath_Backslashes()
|
||||
local result = utils.sanitizePath("C:\\path\\to\\file")
|
||||
luaunit.assertEquals(result, "C:/path/to/file")
|
||||
end
|
||||
|
||||
function TestSanitizePath:testSanitizePath_DuplicateSlashes()
|
||||
local result = utils.sanitizePath("/path//to///file")
|
||||
luaunit.assertEquals(result, "/path/to/file")
|
||||
end
|
||||
|
||||
function TestSanitizePath:testSanitizePath_TrailingSlash()
|
||||
local result = utils.sanitizePath("/path/to/dir/")
|
||||
luaunit.assertEquals(result, "/path/to/dir")
|
||||
|
||||
-- Root should keep trailing slash
|
||||
result = utils.sanitizePath("/")
|
||||
luaunit.assertEquals(result, "/")
|
||||
end
|
||||
|
||||
function TestSanitizePath:testSanitizePath_MixedIssues()
|
||||
local result = utils.sanitizePath(" C:\\path\\\\to///file.txt ")
|
||||
luaunit.assertEquals(result, "C:/path/to/file.txt")
|
||||
end
|
||||
|
||||
-- Test suite for isPathSafe
|
||||
TestIsPathSafe = {}
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_EmptyPath()
|
||||
local safe, reason = utils.isPathSafe("")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "empty")
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_NilPath()
|
||||
local safe, reason = utils.isPathSafe(nil)
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertNotNil(reason)
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_ParentDirectory()
|
||||
local safe, reason = utils.isPathSafe("../etc/passwd")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "..")
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_MultipleParentDirectories()
|
||||
local safe, reason = utils.isPathSafe("../../../../../../etc/passwd")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "..")
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_HiddenParentDirectory()
|
||||
local safe, reason = utils.isPathSafe("/path/to/../../../etc/passwd")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "..")
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_NullBytes()
|
||||
local safe, reason = utils.isPathSafe("/path/to/file\0.txt")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "null")
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_EncodedTraversal()
|
||||
local safe, reason = utils.isPathSafe("/path/%2e%2e/file")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "encoded")
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_LegitimatePathNoBaseDir()
|
||||
local safe, reason = utils.isPathSafe("/themes/default.lua")
|
||||
luaunit.assertTrue(safe)
|
||||
luaunit.assertNil(reason)
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_LegitimatePathWithBaseDir()
|
||||
local safe, reason = utils.isPathSafe("/allowed/themes/default.lua", "/allowed")
|
||||
luaunit.assertTrue(safe)
|
||||
luaunit.assertNil(reason)
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_RelativePathWithBaseDir()
|
||||
local safe, reason = utils.isPathSafe("themes/default.lua", "/allowed")
|
||||
luaunit.assertTrue(safe)
|
||||
luaunit.assertNil(reason)
|
||||
end
|
||||
|
||||
function TestIsPathSafe:testIsPathSafe_OutsideBaseDir()
|
||||
local safe, reason = utils.isPathSafe("/other/themes/default.lua", "/allowed")
|
||||
luaunit.assertFalse(safe)
|
||||
luaunit.assertStrContains(reason, "outside")
|
||||
end
|
||||
|
||||
-- Test suite for validatePath
|
||||
TestValidatePath = {}
|
||||
|
||||
function TestValidatePath:testValidatePath_EmptyPath()
|
||||
local valid, err = utils.validatePath("")
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertStrContains(err, "empty")
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_NilPath()
|
||||
local valid, err = utils.validatePath(nil)
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertStrContains(err, "empty")
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_TooLong()
|
||||
local longPath = string.rep("a", 5000)
|
||||
local valid, err = utils.validatePath(longPath, { maxLength = 100 })
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertStrContains(err, "maximum length")
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_TraversalAttack()
|
||||
local valid, err = utils.validatePath("../../../etc/passwd")
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertNotNil(err)
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_AllowedExtension()
|
||||
local valid, err = utils.validatePath("theme.lua", { allowedExtensions = { "lua", "txt" } })
|
||||
luaunit.assertTrue(valid)
|
||||
luaunit.assertNil(err)
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_DisallowedExtension()
|
||||
local valid, err = utils.validatePath("script.exe", { allowedExtensions = { "lua", "txt" } })
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertStrContains(err, "not allowed")
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_NoExtension()
|
||||
local valid, err = utils.validatePath("README", { allowedExtensions = { "lua", "txt" } })
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertStrContains(err, "no file extension")
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_CaseInsensitiveExtension()
|
||||
local valid, err = utils.validatePath("Theme.LUA", { allowedExtensions = { "lua" } })
|
||||
luaunit.assertTrue(valid)
|
||||
luaunit.assertNil(err)
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_WithBaseDir()
|
||||
local valid, err = utils.validatePath("themes/default.lua", { baseDir = "/allowed" })
|
||||
luaunit.assertTrue(valid)
|
||||
luaunit.assertNil(err)
|
||||
end
|
||||
|
||||
function TestValidatePath:testValidatePath_OutsideBaseDir()
|
||||
local valid, err = utils.validatePath("/other/theme.lua", { baseDir = "/allowed" })
|
||||
luaunit.assertFalse(valid)
|
||||
luaunit.assertStrContains(err, "outside")
|
||||
end
|
||||
|
||||
-- Test suite for getFileExtension
|
||||
TestGetFileExtension = {}
|
||||
|
||||
function TestGetFileExtension:testGetFileExtension_SimpleExtension()
|
||||
local ext = utils.getFileExtension("file.txt")
|
||||
luaunit.assertEquals(ext, "txt")
|
||||
end
|
||||
|
||||
function TestGetFileExtension:testGetFileExtension_MultipleDotsInPath()
|
||||
local ext = utils.getFileExtension("/path/to/file.name.txt")
|
||||
luaunit.assertEquals(ext, "txt")
|
||||
end
|
||||
|
||||
function TestGetFileExtension:testGetFileExtension_NoExtension()
|
||||
local ext = utils.getFileExtension("README")
|
||||
luaunit.assertNil(ext)
|
||||
end
|
||||
|
||||
function TestGetFileExtension:testGetFileExtension_NilPath()
|
||||
local ext = utils.getFileExtension(nil)
|
||||
luaunit.assertNil(ext)
|
||||
end
|
||||
|
||||
function TestGetFileExtension:testGetFileExtension_CaseSensitive()
|
||||
local ext = utils.getFileExtension("File.TXT")
|
||||
luaunit.assertEquals(ext, "txt") -- Should be lowercase
|
||||
end
|
||||
|
||||
function TestGetFileExtension:testGetFileExtension_LongExtension()
|
||||
local ext = utils.getFileExtension("archive.tar.gz")
|
||||
luaunit.assertEquals(ext, "gz")
|
||||
end
|
||||
|
||||
-- Test suite for hasAllowedExtension
|
||||
TestHasAllowedExtension = {}
|
||||
|
||||
function TestHasAllowedExtension:testHasAllowedExtension_Allowed()
|
||||
local allowed = utils.hasAllowedExtension("file.txt", { "txt", "lua" })
|
||||
luaunit.assertTrue(allowed)
|
||||
end
|
||||
|
||||
function TestHasAllowedExtension:testHasAllowedExtension_NotAllowed()
|
||||
local allowed = utils.hasAllowedExtension("file.exe", { "txt", "lua" })
|
||||
luaunit.assertFalse(allowed)
|
||||
end
|
||||
|
||||
function TestHasAllowedExtension:testHasAllowedExtension_CaseInsensitive()
|
||||
local allowed = utils.hasAllowedExtension("File.TXT", { "txt", "lua" })
|
||||
luaunit.assertTrue(allowed)
|
||||
end
|
||||
|
||||
function TestHasAllowedExtension:testHasAllowedExtension_NoExtension()
|
||||
local allowed = utils.hasAllowedExtension("README", { "txt", "lua" })
|
||||
luaunit.assertFalse(allowed)
|
||||
end
|
||||
|
||||
function TestHasAllowedExtension:testHasAllowedExtension_EmptyArray()
|
||||
local allowed = utils.hasAllowedExtension("file.txt", {})
|
||||
luaunit.assertFalse(allowed)
|
||||
end
|
||||
|
||||
-- Test suite for security scenarios
|
||||
TestPathSecurity = {}
|
||||
|
||||
function TestPathSecurity:testPathSecurity_WindowsTraversal()
|
||||
local safe = utils.isPathSafe("..\\..\\..\\windows\\system32")
|
||||
luaunit.assertFalse(safe)
|
||||
end
|
||||
|
||||
function TestPathSecurity:testPathSecurity_MixedSeparators()
|
||||
local safe = utils.isPathSafe("../path\\to/../file")
|
||||
luaunit.assertFalse(safe)
|
||||
end
|
||||
|
||||
function TestPathSecurity:testPathSecurity_DoubleEncodedTraversal()
|
||||
local safe = utils.isPathSafe("%252e%252e%252f")
|
||||
luaunit.assertFalse(safe)
|
||||
end
|
||||
|
||||
function TestPathSecurity:testPathSecurity_LegitimateFileWithDots()
|
||||
-- Files with dots in name should be OK (not ..)
|
||||
local safe = utils.isPathSafe("/path/to/file.backup.txt")
|
||||
luaunit.assertTrue(safe)
|
||||
end
|
||||
|
||||
function TestPathSecurity:testPathSecurity_HiddenFiles()
|
||||
-- Hidden files (starting with .) should be OK
|
||||
local safe = utils.isPathSafe("/path/to/.hidden")
|
||||
luaunit.assertTrue(safe)
|
||||
end
|
||||
|
||||
-- Run tests if this file is executed directly
|
||||
if not _G.RUNNING_ALL_TESTS then
|
||||
os.exit(luaunit.LuaUnit.run())
|
||||
end
|
||||
Reference in New Issue
Block a user