Facebook
From i, 1 Year ago, written in Lua.
Embed
Download Paste or View Raw
Hits: 874
  1. assert = function(a, b)
  2.  if not a then warn(b) end
  3. end
  4.  
  5. local passes, fails, undefined = 0, 0, 0
  6. local running = 0
  7.  
  8. local function getGlobal(path)
  9.  local value = getgenv and getgenv() or getfenv(2)
  10.  
  11.  while value ~= nil and path ~= "" do
  12.   local name, nextValue = string.match(path, "^([^.]+)%.?(.*)$")
  13.   value = value[name]
  14.   path = nextValue
  15.  end
  16.  
  17.  return value
  18. end
  19.  
  20. local function test(name, aliases, callback, target)
  21.  running = running + 1
  22.  
  23.  task.spawn(function()
  24.   if not callback then
  25.    print("⏺️ " .. name)
  26.   elseif not getGlobal(name) then
  27.    fails = fails + 1
  28.    warn("⛔ " .. name)
  29.   else
  30.    local success, message = pcall(callback)
  31.          name = tostring(name)
  32.    message = tostring(message)
  33.    if success then
  34.     passes = passes + 1
  35.     print("✅ " .. tostring(name) .. (tostring(message) and " • " .. tostring(message) or ""))
  36.    else
  37.     fails = fails + 1
  38.     warn("⛔ " .. name .. " failed: " .. message)
  39.    end
  40.   end
  41.  
  42.   local undefinedAliases = {}
  43.  
  44.   for _, alias in ipairs(aliases) do
  45.    if getGlobal(alias) == nil then
  46.     table.insert(undefinedAliases, alias)
  47.    end
  48.   end
  49.  
  50.   if #undefinedAliases > 0 then
  51.    undefined = undefined + 1
  52.    warn("⚠️ " .. table.concat(undefinedAliases, ", "))
  53.   end
  54.  
  55.   running = running - 1
  56.  end)
  57. end
  58.  
  59. -- Header and summary
  60.  
  61. print("\n")
  62.  
  63. print("UNC Environment Check")
  64. print("✅ - Pass, ⛔ - Fail, ⏺️ - No test, ⚠️ - Missing aliases\n")
  65.  
  66. task.defer(function()
  67.  repeat task.wait() until running == 0
  68.  
  69.  local rate = math.round(passes / (passes + fails) * 100)
  70.  local outOf = passes .. " out of " .. (passes + fails)
  71.  
  72.  print("\n")
  73.  
  74.  print("UNC Summary")
  75.  print("✅ Tested with a " .. rate .. "% success rate (" .. outOf .. ")")
  76.  print("⛔ " .. fails .. " tests failed")
  77.  print("⚠️ " .. undefined .. " globals are missing aliases")
  78. end)
  79.  
  80. -- Cache
  81.  
  82. test("cache.invalidate", {}, function()
  83.  local container = Instance.new("Folder")
  84.  local part = Instance.new("Part", container)
  85.  cache.invalidate(container:FindFirstChild("Part"))
  86.  assert(part ~= container:FindFirstChild("Part"), "Reference `part` could not be invalidated")
  87. end)
  88.  
  89. test("cache.iscached", {}, function()
  90.  local part = Instance.new("Part")
  91.  assert(cache.iscached(part), "Part should be cached")
  92.  cache.invalidate(part)
  93.  assert(not cache.iscached(part), "Part should not be cached")
  94. end)
  95.  
  96. test("cache.replace", {}, function()
  97.  local part = Instance.new("Part")
  98.  local fire = Instance.new("Fire")
  99.  cache.replace(part, fire)
  100.  assert(part ~= fire, "Part was not replaced with Fire")
  101. end)
  102.  
  103. test("cloneref", {}, function()
  104.  local part = Instance.new("Part")
  105.  local clone = cloneref(part)
  106.  assert(part ~= clone, "Clone should not be equal to original")
  107.  clone.Name = "Test"
  108.  assert(part.Name == "Test", "Clone should have updated the original")
  109. end)
  110.  
  111. test("compareinstances", {}, function()
  112.  local part = Instance.new("Part")
  113.  local clone = cloneref(part)
  114.  assert(part ~= clone, "Clone should not be equal to original")
  115.  assert(compareinstances(part, clone), "Clone should be equal to original when using compareinstances()")
  116. end)
  117.  
  118. -- Closures
  119.  
  120. local function shallowEqual(t1, t2)
  121.  if t1 == t2 then
  122.   return true
  123.  end
  124.  
  125.  local UNIQUE_TYPES = {
  126.   ["function"] = true,
  127.   ["table"] = true,
  128.   ["userdata"] = true,
  129.   ["thread"] = true,
  130.  }
  131.  
  132.  for k, v in pairs(t1) do
  133.   if UNIQUE_TYPES[type(v)] then
  134.    if type(t2[k]) ~= type(v) then
  135.     return false
  136.    end
  137.   elseif t2[k] ~= v then
  138.    return false
  139.   end
  140.  end
  141.  
  142.  for k, v in pairs(t2) do
  143.   if UNIQUE_TYPES[type(v)] then
  144.    if type(t2[k]) ~= type(v) then
  145.     return false
  146.    end
  147.   elseif t1[k] ~= v then
  148.    return false
  149.   end
  150.  end
  151.  
  152.  return true
  153. end
  154.  
  155. test("checkcaller", {}, function()
  156.  assert(checkcaller(), "Main scope should return true")
  157. end)
  158.  
  159. test("clonefunction", {}, function()
  160.  local function test()
  161.   return "success"
  162.  end
  163.  local copy = clonefunction(test)
  164.  assert(test() == copy(), "The clone should return the same value as the original")
  165.  assert(test ~= copy, "The clone should not be equal to the original")
  166. end)
  167.  
  168. test("getcallingscript", {})
  169.  
  170. test("getscriptclosure", {"getscriptfunction"}, function()
  171.  local module = game:GetService("CoreGui").RobloxGui.Modules.Common.Constants
  172.  local constants = getrenv().require(module)
  173.  local generated = getscriptclosure(module)()
  174.  assert(constants ~= generated, "Generated module should not match the original")
  175.  assert(shallowEqual(constants, generated), "Generated constant table should be shallow equal to the original")
  176. end)
  177.  
  178. test("hookfunction", {"replaceclosure"}, function()
  179.  local function test()
  180.   return true
  181.  end
  182.  local ref = hookfunction(test, function()
  183.   return false
  184.  end)
  185.  assert(test() == false, "Function should return false")
  186.  assert(ref() == true, "Original function should return true")
  187.  assert(test ~= ref, "Original function should not be same as the reference")
  188. end)
  189.  
  190. test("iscclosure", {}, function()
  191.  assert(iscclosure(print) == true, "Function 'print' should be a C closure")
  192.  assert(iscclosure(function() end) == false, "Executor function should not be a C closure")
  193. end)
  194.  
  195. test("islclosure", {}, function()
  196.  assert(islclosure(print) == false, "Function 'print' should not be a Lua closure")
  197.  assert(islclosure(function() end) == true, "Executor function should be a Lua closure")
  198. end)
  199.  
  200. test("isexecutorclosure", {"checkclosure", "isourclosure"}, function()
  201.  assert(isexecutorclosure(isexecutorclosure) == true, "Did not return true for an executor global")
  202.  assert(isexecutorclosure(newcclosure(function() end)) == true, "Did not return true for an executor C closure")
  203.  assert(isexecutorclosure(function() end) == true, "Did not return true for an executor Luau closure")
  204.  assert(isexecutorclosure(print) == false, "Did not return false for a Roblox global")
  205. end)
  206.  
  207. test("loadstring", {}, function()
  208.  local animate = game:GetService("Players").LocalPlayer.Character.Animate
  209.  local bytecode = getscriptbytecode(animate)
  210.  local func = loadstring(bytecode)
  211.  assert(type(func) ~= "function", "Luau bytecode should not be loadable!")
  212.  assert(assert(loadstring("return ... + 1"))(1) == 2, "Failed to do simple math")
  213.  assert(type(select(2, loadstring("f"))) == "string", "Loadstring did not return anything for a compiler error")
  214. end)
  215.  
  216. test("newcclosure", {}, function()
  217.  local function test()
  218.   return true
  219.  end
  220.  local testC = newcclosure(test)
  221.  assert(test() == testC(), "New C closure should return the same value as the original")
  222.  assert(test ~= testC, "New C closure should not be same as the original")
  223.  assert(iscclosure(testC), "New C closure should be a C closure")
  224. end)
  225.  
  226. -- Console
  227.  
  228. test("rconsoleclear", {"consoleclear"})
  229.  
  230. test("rconsolecreate", {"consolecreate"})
  231.  
  232. test("rconsoledestroy", {"consoledestroy"})
  233.  
  234. test("rconsoleinput", {"consoleinput"})
  235.  
  236. test("rconsoleprint", {"consoleprint"})
  237.  
  238. test("rconsolesettitle", {"rconsolename", "consolesettitle"})
  239.  
  240. -- Crypt
  241.  
  242. test("crypt.base64encode", {"crypt.base64.encode", "crypt.base64_encode", "base64.encode", "base64_encode"}, function()
  243.  assert(crypt.base64encode("test") == "dGVzdA==", "Base64 encoding failed")
  244. end)
  245.  
  246. test("crypt.base64decode", {"crypt.base64.decode", "crypt.base64_decode", "base64.decode", "base64_decode"}, function()
  247.  assert(crypt.base64decode("dGVzdA==") == "test", "Base64 decoding failed")
  248. end)
  249.  
  250. test("crypt.encrypt", {}, function()
  251.  local key = crypt.generatekey()
  252.  local encrypted, iv = crypt.encrypt("test", key, nil, "CBC")
  253.  assert(iv, "crypt.encrypt should return an IV")
  254.  local decrypted = crypt.decrypt(encrypted, key, iv, "CBC")
  255.  assert(decrypted == "test", "Failed to decrypt raw string from encrypted data")
  256. end)
  257.  
  258. test("crypt.decrypt", {}, function()
  259.  local key, iv = crypt.generatekey(), crypt.generatekey()
  260.  local encrypted = crypt.encrypt("test", key, iv, "CBC")
  261.  local decrypted = crypt.decrypt(encrypted, key, iv, "CBC")
  262.  assert(decrypted == "test", "Failed to decrypt raw string from encrypted data")
  263. end)
  264.  
  265. test("crypt.generatebytes", {}, function()
  266.  local size = math.random(10, 100)
  267.  local bytes = crypt.generatebytes(size)
  268.  assert(#crypt.base64decode(bytes) == size, "The decoded result should be " .. size .. " bytes long (got " .. #crypt.base64decode(bytes) .. " decoded, " .. #bytes .. " raw)")
  269. end)
  270.  
  271. test("crypt.generatekey", {}, function()
  272.  local key = crypt.generatekey()
  273.  assert(#crypt.base64decode(key) == 32, "Generated key should be 32 bytes long when decoded")
  274. end)
  275.  
  276. test("crypt.hash", {}, function()
  277.  local algorithms = {'sha1', 'sha384', 'sha512', 'md5', 'sha256', 'sha3-224', 'sha3-256', 'sha3-512'}
  278.  for _, algorithm in ipairs(algorithms) do
  279.   local hash = crypt.hash("test", algorithm)
  280.   assert(hash, "crypt.hash on algorithm '" .. algorithm .. "' should return a hash")
  281.  end
  282. end)
  283.  
  284. --- Debug
  285.  
  286. test("debug.getconstant", {}, function()
  287.  local function test()
  288.   print("Hello, world!")
  289.  end
  290.  assert(debug.getconstant(test, 1) == "print", "First constant must be print")
  291.  assert(debug.getconstant(test, 2) == nil, "Second constant must be nil")
  292.  assert(debug.getconstant(test, 3) == "Hello, world!", "Third constant must be 'Hello, world!'")
  293. end)
  294.  
  295. test("debug.getconstants", {}, function()
  296.  local function test()
  297.   local num = 5000 .. 50000
  298.   print("Hello, world!", num, warn)
  299.  end
  300.  local constants = debug.getconstants(test)
  301.  assert(constants[1] == 50000, "First constant must be 50000")
  302.  assert(constants[2] == "print", "Second constant must be print")
  303.  assert(constants[3] == nil, "Third constant must be nil")
  304.  assert(constants[4] == "Hello, world!", "Fourth constant must be 'Hello, world!'")
  305.  assert(constants[5] == "warn", "Fifth constant must be warn")
  306. end)
  307.  
  308. test("debug.getinfo", {}, function()
  309.  local types = {
  310.   source = "string",
  311.   short_src = "string",
  312.   func = "function",
  313.   what = "string",
  314.   currentline = "number",
  315.   name = "string",
  316.   nups = "number",
  317.   numparams = "number",
  318.   is_vararg = "number",
  319.  }
  320.  local function test(...)
  321.   print(...)
  322.  end
  323.  local info = debug.getinfo(test)
  324.  for k, v in pairs(types) do
  325.   assert(info[k] ~= nil, "Did not return a table with a '" .. k .. "' field")
  326.   assert(type(info[k]) == v, "Did not return a table with " .. k .. " as a " .. v .. " (got " .. type(info[k]) .. ")")
  327.  end
  328. end)
  329.  
  330. test("debug.getproto", {}, function()
  331.  local function test()
  332.   local function proto()
  333.    return true
  334.   end
  335.  end
  336.  local proto = debug.getproto(test, 1, true)[1]
  337.  local realproto = debug.getproto(test, 1)
  338.  assert(proto, "Failed to get the inner function")
  339.  assert(proto() == true, "The inner function did not return anything")
  340.  if not realproto() then
  341.   return "Proto return values are disabled on this executor"
  342.  end
  343. end)
  344.  
  345. test("debug.getprotos", {}, function()
  346.  local function test()
  347.   local function _1()
  348.    return true
  349.   end
  350.   local function _2()
  351.    return true
  352.   end
  353.   local function _3()
  354.    return true
  355.   end
  356.  end
  357.  for i in ipairs(debug.getprotos(test)) do
  358.   local proto = debug.getproto(test, i, true)[1]
  359.   local realproto = debug.getproto(test, i)
  360.   assert(proto(), "Failed to get inner function " .. i)
  361.   if not realproto() then
  362.    return "Proto return values are disabled on this executor"
  363.   end
  364.  end
  365. end)
  366.  
  367. test("debug.getstack", {}, function()
  368.  local _ = "a" .. "b"
  369.  assert(debug.getstack(1, 1) == "ab", "The first item in the stack should be 'ab'")
  370.  assert(debug.getstack(1)[1] == "ab", "The first item in the stack table should be 'ab'")
  371. end)
  372.  
  373. test("debug.getupvalue", {}, function()
  374.  local upvalue = function() end
  375.  local function test()
  376.   print(upvalue)
  377.  end
  378.  assert(debug.getupvalue(test, 1) == upvalue, "Unexpected value returned from debug.getupvalue")
  379. end)
  380.  
  381. test("debug.getupvalues", {}, function()
  382.  local upvalue = function() end
  383.  local function test()
  384.   print(upvalue)
  385.  end
  386.  local upvalues = debug.getupvalues(test)
  387.  assert(upvalues[1] == upvalue, "Unexpected value returned from debug.getupvalues")
  388. end)
  389.  
  390. test("debug.setconstant", {}, function()
  391.  local function test()
  392.   return "fail"
  393.  end
  394.  debug.setconstant(test, 1, "success")
  395.  assert(test() == "success", "debug.setconstant did not set the first constant")
  396. end)
  397.  
  398. test("debug.setstack", {}, function()
  399.  local function test()
  400.   return "fail", debug.setstack(1, 1, "success")
  401.  end
  402.  assert(test() == "success", "debug.setstack did not set the first stack item")
  403. end)
  404.  
  405. test("debug.setupvalue", {}, function()
  406.  local function upvalue()
  407.   return "fail"
  408.  end
  409.  local function test()
  410.   return upvalue()
  411.  end
  412.  debug.setupvalue(test, 1, function()
  413.   return "success"
  414.  end)
  415.  assert(test() == "success", "debug.setupvalue did not set the first upvalue")
  416. end)
  417.  
  418. -- Filesystem
  419.  
  420. if isfolder and makefolder and delfolder then
  421.  if isfolder(".tests") then
  422.   delfolder(".tests")
  423.  end
  424.  makefolder(".tests")
  425. end
  426.  
  427. test("readfile", {}, function()
  428.  writefile(".tests/readfile.txt", "success")
  429.  assert(readfile(".tests/readfile.txt") == "success", "Did not return the contents of the file")
  430. end)
  431.  
  432. test("listfiles", {}, function()
  433.  makefolder(".tests/listfiles")
  434.  writefile(".tests/listfiles/test_1.txt", "success")
  435.  writefile(".tests/listfiles/test_2.txt", "success")
  436.  local files = listfiles(".tests/listfiles")
  437.  assert(#files == 2, "Did not return the correct number of files")
  438.  assert(isfile(files[1]), "Did not return a file path")
  439.  assert(readfile(files[1]) == "success", "Did not return the correct files")
  440.  makefolder(".tests/listfiles_2")
  441.  makefolder(".tests/listfiles_2/test_1")
  442.  makefolder(".tests/listfiles_2/test_2")
  443.  local folders = listfiles(".tests/listfiles_2")
  444.  assert(#folders == 2, "Did not return the correct number of folders")
  445.  assert(isfolder(folders[1]), "Did not return a folder path")
  446. end)
  447.  
  448. test("writefile", {}, function()
  449.  writefile(".tests/writefile.txt", "success")
  450.  assert(readfile(".tests/writefile.txt") == "success", "Did not write the file")
  451.  local requiresFileExt = pcall(function()
  452.   writefile(".tests/writefile", "success")
  453.   assert(isfile(".tests/writefile.txt"))
  454.  end)
  455.  if not requiresFileExt then
  456.   return "This executor requires a file extension in writefile"
  457.  end
  458. end)
  459.  
  460. test("makefolder", {}, function()
  461.  makefolder(".tests/makefolder")
  462.  assert(isfolder(".tests/makefolder"), "Did not create the folder")
  463. end)
  464.  
  465. test("appendfile", {}, function()
  466.  writefile(".tests/appendfile.txt", "su")
  467.  appendfile(".tests/appendfile.txt", "cce")
  468.  appendfile(".tests/appendfile.txt", "ss")
  469.  assert(readfile(".tests/appendfile.txt") == "success", "Did not append the file")
  470. end)
  471.  
  472. test("isfile", {}, function()
  473.  writefile(".tests/isfile.txt", "success")
  474.  assert(isfile(".tests/isfile.txt") == true, "Did not return true for a file")
  475.  assert(isfile(".tests") == false, "Did not return false for a folder")
  476.  assert(isfile(".tests/doesnotexist.exe") == false, "Did not return false for a nonexistent path (got " .. tostring(isfile(".tests/doesnotexist.exe")) .. ")")
  477. end)
  478.  
  479. test("isfolder", {}, function()
  480.  assert(isfolder(".tests") == true, "Did not return false for a folder")
  481.  assert(isfolder(".tests/doesnotexist.exe") == false, "Did not return false for a nonexistent path (got " .. tostring(isfolder(".tests/doesnotexist.exe")) .. ")")
  482. end)
  483.  
  484. test("delfolder", {}, function()
  485.  makefolder(".tests/delfolder")
  486.  delfolder(".tests/delfolder")
  487.  assert(isfolder(".tests/delfolder") == false, "Failed to delete folder (isfolder = " .. tostring(isfolder(".tests/delfolder")) .. ")")
  488. end)
  489.  
  490. test("delfile", {}, function()
  491.  writefile(".tests/delfile.txt", "Hello, world!")
  492.  delfile(".tests/delfile.txt")
  493.  assert(isfile(".tests/delfile.txt") == false, "Failed to delete file (isfile = " .. tostring(isfile(".tests/delfile.txt")) .. ")")
  494. end)
  495.  
  496. test("dofile", {})
  497.  
  498. -- Input
  499.  
  500. test("isrbxactive", {"isgameactive"}, function()
  501.  assert(type(isrbxactive()) == "boolean", "Did not return a boolean value")
  502. end)
  503.  
  504. test("mouse1click", {})
  505.  
  506. test("mouse1press", {})
  507.  
  508. test("mouse1release", {})
  509.  
  510. test("mouse2click", {})
  511.  
  512. test("mouse2press", {})
  513.  
  514. test("mouse2release", {})
  515.  
  516. test("mousemoveabs", {})
  517.  
  518. test("mousemoverel", {})
  519.  
  520. test("mousescroll", {})
  521.  
  522. -- Instances
  523.  
  524. test("fireclickdetector", {}, function()
  525.  local detector = Instance.new("ClickDetector")
  526.  fireclickdetector(detector, 50, "MouseHoverEnter")
  527. end)
  528.  
  529. test("getcallbackvalue", {}, function()
  530.  local bindable = Instance.new("BindableFunction")
  531.  local function test()
  532.  end
  533.  bindable.OnInvoke = test
  534.  assert(getcallbackvalue(bindable, "OnInvoke") == test, "Did not return the correct value")
  535. end)
  536.  
  537. test("getconnections", {}, function()
  538.  local types = {
  539.   Enabled = "boolean",
  540.   ForeignState = "boolean",
  541.   LuaConnection = "boolean",
  542.   Function = "function",
  543.   Thread = "thread",
  544.   Fire = "function",
  545.   Defer = "function",
  546.   Disconnect = "function",
  547.   Disable = "function",
  548.   Enable = "function",
  549.  }
  550.  local bindable = Instance.new("BindableEvent")
  551.  bindable.Event:Connect(function() end)
  552.  local connection = getconnections(bindable.Event)[1]
  553.  for k, v in pairs(types) do
  554.   assert(connection[k] ~= nil, "Did not return a table with a '" .. k .. "' field")
  555.   assert(type(connection[k]) == v, "Did not return a table with " .. k .. " as a " .. v .. " (got " .. type(connection[k]) .. ")")
  556.  end
  557. end)
  558.  
  559. test("getcustomasset", {}, function()
  560.  writefile(".tests/getcustomasset.txt", "success")
  561.  local contentId = getcustomasset(".tests/getcustomasset.txt")
  562.  assert(type(contentId) == "string", "Did not return a string")
  563.  assert(#contentId > 0, "Returned an empty string")
  564.  assert(string.match(contentId, "rbxasset://") == "rbxasset://", "Did not return an rbxasset url")
  565. end)
  566.  
  567. test("gethiddenproperty", {}, function()
  568.  local fire = Instance.new("Fire")
  569.  local property, isHidden = gethiddenproperty(fire, "size_xml")
  570.  assert(property == 5, "Did not return the correct value")
  571.  assert(isHidden == true, "Did not return whether the property was hidden")
  572. end)
  573.  
  574. test("sethiddenproperty", {}, function()
  575.  local fire = Instance.new("Fire")
  576.  local hidden = sethiddenproperty(fire, "size_xml", 10)
  577.  assert(hidden, "Did not return true for the hidden property")
  578.  assert(gethiddenproperty(fire, "size_xml") == 10, "Did not set the hidden property")
  579. end)
  580.  
  581. test("gethui", {}, function()
  582.  assert(typeof(gethui()) == "Instance", "Did not return an Instance")
  583. end)
  584.  
  585. test("getinstances", {}, function()
  586.  assert(getinstances()[1]:IsA("Instance"), "The first value is not an Instance")
  587. end)
  588.  
  589. test("getnilinstances", {}, function()
  590.  assert(getnilinstances()[1]:IsA("Instance"), "The first value is not an Instance")
  591.  assert(getnilinstances()[1].Parent == nil, "The first value is not parented to nil")
  592. end)
  593.  
  594. test("isscriptable", {}, function()
  595.  local fire = Instance.new("Fire")
  596.  assert(isscriptable(fire, "size_xml") == false, "Did not return false for a non-scriptable property (size_xml)")
  597.  assert(isscriptable(fire, "Size") == true, "Did not return true for a scriptable property (Size)")
  598. end)
  599.  
  600. test("setscriptable", {}, function()
  601.  local fire = Instance.new("Fire")
  602.  local wasScriptable = setscriptable(fire, "size_xml", true)
  603.  assert(wasScriptable == false, "Did not return false for a non-scriptable property (size_xml)")
  604.  assert(isscriptable(fire, "size_xml") == true, "Did not set the scriptable property")
  605.  fire = Instance.new("Fire")
  606.  assert(isscriptable(fire, "size_xml") == false, "⚠️⚠️ setscriptable persists between unique instances ⚠️⚠️")
  607. end)
  608.  
  609. test("setrbxclipboard", {})
  610.  
  611. -- Metatable
  612.  
  613. test("getrawmetatable", {}, function()
  614.  local metatable = { __metatable = "Locked!" }
  615.  local object = setmetatable({}, metatable)
  616.  assert(getrawmetatable(object) == metatable, "Did not return the metatable")
  617. end)
  618.  
  619. test("hookmetamethod", {}, function()
  620.  local object = setmetatable({}, { __index = newcclosure(function() return false end), __metatable = "Locked!" })
  621.  local ref = hookmetamethod(object, "__index", function() return true end)
  622.  assert(object.test == true, "Failed to hook a metamethod and change the return value")
  623.  assert(ref() == false, "Did not return the original function")
  624. end)
  625.  
  626. test("getnamecallmethod", {}, function()
  627.  local method
  628.  local ref
  629.  ref = hookmetamethod(game, "__namecall", function(...)
  630.   if not method then
  631.    method = getnamecallmethod()
  632.   end
  633.   return ref(...)
  634.  end)
  635.  game:GetService("Lighting")
  636.  assert(method == "GetService", "Did not get the correct method (GetService)")
  637. end)
  638.  
  639. test("isreadonly", {}, function()
  640.  local object = {}
  641.  table.freeze(object)
  642.  assert(isreadonly(object), "Did not return true for a read-only table")
  643. end)
  644.  
  645. test("setrawmetatable", {}, function()
  646.  local object = setmetatable({}, { __index = function() return false end, __metatable = "Locked!" })
  647.  local objectReturned = setrawmetatable(object, { __index = function() return true end })
  648.  assert(object, "Did not return the original object")
  649.  assert(object.test == true, "Failed to change the metatable")
  650.  if objectReturned then
  651.   return objectReturned == object and "Returned the original object" or "Did not return the original object"
  652.  end
  653. end)
  654.  
  655. test("setreadonly", {}, function()
  656.  local object = { success = false }
  657.  table.freeze(object)
  658.  setreadonly(object, false)
  659.  object.success = true
  660.  assert(object.success, "Did not allow the table to be modified")
  661. end)
  662.  
  663. -- Miscellaneous
  664.  
  665. test("identifyexecutor", {"getexecutorname"}, function()
  666.  local name, version = identifyexecutor()
  667.  assert(type(name) == "string", "Did not return a string for the name")
  668.  return type(version) == "string" and "Returns version as a string" or "Does not return version"
  669. end)
  670.  
  671. test("lz4compress", {}, function()
  672.  local raw = "Hello, world!"
  673.  local compressed = lz4compress(raw)
  674.  assert(type(compressed) == "string", "Compression did not return a string")
  675.  assert(lz4decompress(compressed, #raw) == raw, "Decompression did not return the original string")
  676. end)
  677.  
  678. test("lz4decompress", {}, function()
  679.  local raw = "Hello, world!"
  680.  local compressed = lz4compress(raw)
  681.  assert(type(compressed) == "string", "Compression did not return a string")
  682.  assert(lz4decompress(compressed, #raw) == raw, "Decompression did not return the original string")
  683. end)
  684.  
  685. test("messagebox", {})
  686.  
  687. test("queue_on_teleport", {"queueonteleport"})
  688.  
  689. test("request", {"http.request", "http_request"}, function()
  690.  local response = request({
  691.   Url = "https://httpbin.org/user-agent",
  692.   Method = "GET",
  693.  })
  694.  assert(type(response) == "table", "Response must be a table")
  695.  assert(response.StatusCode == 200, "Did not return a 200 status code")
  696.  local data = game:GetService("HttpService"):JSONDecode(response.Body)
  697.  assert(type(data) == "table" and type(data["user-agent"]) == "string", "Did not return a table with a user-agent key")
  698.  return "User-Agent: " .. data["user-agent"]
  699. end)
  700.  
  701. test("setclipboard", {"toclipboard"})
  702.  
  703. test("setfpscap", {}, function()
  704.  local renderStepped = game:GetService("RunService").RenderStepped
  705.  local function step()
  706.   renderStepped:Wait()
  707.   local sum = 0
  708.   for _ = 1, 5 do
  709.    sum = sum + 1 / renderStepped:Wait()
  710.   end
  711.   return math.round(sum / 5)
  712.  end
  713.  setfpscap(60)
  714.  local step60 = step()
  715.  setfpscap(0)
  716.  local step0 = step()
  717.  return step60 .. "fps @60 • " .. step0 .. "fps @0"
  718. end)
  719.  
  720. -- Scripts
  721.  
  722. test("getgc", {}, function()
  723.  local gc = getgc()
  724.  assert(type(gc) == "table", "Did not return a table")
  725.  assert(#gc > 0, "Did not return a table with any values")
  726. end)
  727.  
  728. test("getgenv", {}, function()
  729.  getgenv().__TEST_GLOBAL = true
  730.  assert(__TEST_GLOBAL, "Failed to set a global variable")
  731.  getgenv().__TEST_GLOBAL = nil
  732. end)
  733.  
  734. test("getloadedmodules", {}, function()
  735.  local modules = getloadedmodules()
  736.  assert(type(modules) == "table", "Did not return a table")
  737.  assert(#modules > 0, "Did not return a table with any values")
  738.  assert(typeof(modules[1]) == "Instance", "First value is not an Instance")
  739.  assert(modules[1]:IsA("ModuleScript"), "First value is not a ModuleScript")
  740. end)
  741.  
  742. test("getrenv", {}, function()
  743.  assert(_G ~= getrenv()._G, "The variable _G in the executor is identical to _G in the game")
  744. end)
  745.  
  746. test("getrunningscripts", {}, function()
  747.  local scripts = getrunningscripts()
  748.  assert(type(scripts) == "table", "Did not return a table")
  749.  assert(#scripts > 0, "Did not return a table with any values")
  750.  assert(typeof(scripts[1]) == "Instance", "First value is not an Instance")
  751.  assert(scripts[1]:IsA("ModuleScript") or scripts[1]:IsA("LocalScript"), "First value is not a ModuleScript or LocalScript")
  752. end)
  753.  
  754. test("getscriptbytecode", {"dumpstring"}, function()
  755.  local animate = game:GetService("Players").LocalPlayer.Character.Animate
  756.  local bytecode = getscriptbytecode(animate)
  757.  assert(type(bytecode) == "string", "Did not return a string for Character.Animate (a " .. animate.ClassName .. ")")
  758. end)
  759.  
  760. test("getscripthash", {}, function()
  761.  local animate = game:GetService("Players").LocalPlayer.Character.Animate:Clone()
  762.  local hash = getscripthash(animate)
  763.  local source = animate.Source
  764.  animate.Source = "print('Hello, world!')"
  765.  task.defer(function()
  766.   animate.Source = source
  767.  end)
  768.  local newHash = getscripthash(animate)
  769.  assert(hash ~= newHash, "Did not return a different hash for a modified script")
  770.  assert(newHash == getscripthash(animate), "Did not return the same hash for a script with the same source")
  771. end)
  772.  
  773. test("getscripts", {}, function()
  774.  local scripts = getscripts()
  775.  assert(type(scripts) == "table", "Did not return a table")
  776.  assert(#scripts > 0, "Did not return a table with any values")
  777.  assert(typeof(scripts[1]) == "Instance", "First value is not an Instance")
  778.  assert(scripts[1]:IsA("ModuleScript") or scripts[1]:IsA("LocalScript"), "First value is not a ModuleScript or LocalScript")
  779. end)
  780.  
  781. test("getsenv", {}, function()
  782.  local animate = game:GetService("Players").LocalPlayer.Character.Animate
  783.  local env = getsenv(animate)
  784.  assert(type(env) == "table", "Did not return a table for Character.Animate (a " .. animate.ClassName .. ")")
  785.  assert(env.script == animate, "The script global is not identical to Character.Animate")
  786. end)
  787.  
  788. test("getthreadidentity", {"getidentity", "getthreadcontext"}, function()
  789.  assert(type(getthreadidentity()) == "number", "Did not return a number")
  790. end)
  791.  
  792. test("setthreadidentity", {"setidentity", "setthreadcontext"}, function()
  793.  setthreadidentity(3)
  794.  assert(getthreadidentity() == 3, "Did not set the thread identity")
  795. end)
  796.  
  797. -- Drawing
  798.  
  799. test("Drawing", {})
  800.  
  801. test("Drawing.new", {}, function()
  802.  local drawing = Drawing.new("Square")
  803.  drawing.Visible = false
  804.  local canDestroy = pcall(function()
  805.   drawing:Destroy()
  806.  end)
  807.  assert(canDestroy, "Drawing:Destroy() should not throw an error")
  808. end)
  809.  
  810. test("Drawing.Fonts", {}, function()
  811.  assert(Drawing.Fonts.UI == 0, "Did not return the correct id for UI")
  812.  assert(Drawing.Fonts.System == 1, "Did not return the correct id for System")
  813.  assert(Drawing.Fonts.Plex == 2, "Did not return the correct id for Plex")
  814.  assert(Drawing.Fonts.Monospace == 3, "Did not return the correct id for Monospace")
  815. end)
  816.  
  817. test("isrenderobj", {}, function()
  818.  local drawing = Drawing.new("Image")
  819.  drawing.Visible = true
  820.  assert(isrenderobj(drawing) == true, "Did not return true for an Image")
  821.  assert(isrenderobj(newproxy()) == false, "Did not return false for a blank table")
  822. end)
  823.  
  824. test("getrenderproperty", {}, function()
  825.  local drawing = Drawing.new("Image")
  826.  drawing.Visible = true
  827.  assert(type(getrenderproperty(drawing, "Visible")) == "boolean", "Did not return a boolean value for Image.Visible")
  828.  local success, result = pcall(function()
  829.   return getrenderproperty(drawing, "Color")
  830.  end)
  831.  if not success or not result then
  832.   return "Image.Color is not supported"
  833.  end
  834. end)
  835.  
  836. test("setrenderproperty", {}, function()
  837.  local drawing = Drawing.new("Square")
  838.  drawing.Visible = true
  839.  setrenderproperty(drawing, "Visible", false)
  840.  assert(drawing.Visible == false, "Did not set the value for Square.Visible")
  841. end)
  842.  
  843. test("cleardrawcache", {}, function()
  844.  cleardrawcache()
  845. end)
  846.  
  847. -- WebSocket
  848.  
  849. test("WebSocket", {})
  850.  
  851. test("WebSocket.connect", {}, function()
  852.  local types = {
  853.   Send = "function",
  854.   Close = "function",
  855.   OnMessage = {"table", "userdata"},
  856.   OnClose = {"table", "userdata"},
  857.  }
  858.  local ws = WebSocket.connect("ws://echo.websocket.events")
  859.  assert(type(ws) == "table" or type(ws) == "userdata", "Did not return a table or userdata")
  860.  for k, v in pairs(types) do
  861.   if type(v) == "table" then
  862.    assert(table.find(v, type(ws[k])), "Did not return a " .. table.concat(v, ", ") .. " for " .. k .. " (a " .. type(ws[k]) .. ")")
  863.   else
  864.    assert(type(ws[k]) == v, "Did not return a " .. v .. " for " .. k .. " (a " .. type(ws[k]) .. ")")
  865.   end
  866.  end
  867.  ws:Close()
  868. end)