-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 690234d
Showing
9 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# Project place file | ||
/tests.rbxlx | ||
|
||
# Roblox Studio lock files | ||
/*.rbxlx.lock | ||
/*.rbxl.lock | ||
|
||
# roblox-ts | ||
node_modules | ||
tests.rbxl |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<div align="center"> | ||
<h1>MockMemoryStoreService</h1> | ||
<h3>Emulation of Roblox's <b>MemoryStoreService</b> for offline development and testing</h3> | ||
</div> | ||
|
||
This is a set of modules, similar to [MockDataStoreService](https://github.com/buildthomas/MockDataStoreService) by buildthomas. This emulates the memory store service rather than using the actual service. This allows for testing it in offline places/local place files with code or frameworks that require the use of MemoryStoreService. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
local httpService = game:GetService("HttpService") | ||
|
||
local MockMemoryStoreQueue = {} | ||
MockMemoryStoreQueue.__index = MockMemoryStoreQueue; | ||
|
||
type Value = { | ||
id: string, | ||
value: any, | ||
expiration: number, | ||
priority: number, | ||
mutex: boolean, | ||
} | ||
|
||
function MockMemoryStoreQueue.new(name) | ||
return setmetatable({ | ||
__queue = {}, | ||
__refs = {} | ||
}, MockMemoryStoreQueue) | ||
end | ||
|
||
function MockMemoryStoreQueue:ReadAsync(count, allOrNothing, waitTimeout) | ||
local results = table.move(#self.__queue - count, #self.__queue, 1, #self.__queue, {}) | ||
|
||
local ref = httpService:GenerateGUID(false) | ||
self.__refs[ref] = results | ||
|
||
for _, value in ipairs(results) do | ||
value.mutex = true | ||
end | ||
return results | ||
end | ||
|
||
function MockMemoryStoreQueue:RemoveAsync(ref) | ||
local valueRef = self.__refs[ref] | ||
if valueRef then | ||
for _, value in ipairs(valueRef) do | ||
local index = table.find(self.__queue, value) | ||
table.remove(self.__queue, index) | ||
end | ||
end | ||
end | ||
|
||
function MockMemoryStoreQueue:AddAsync(value: any, expiration: number, priority: number) | ||
table.insert(self.__queue, { | ||
value = value, | ||
expiration = expiration, | ||
priority = priority, | ||
id = httpService:GenerateGUID(false), | ||
mutex = false | ||
} :: Value) | ||
|
||
table.sort(self.__queue, function(a: Value, b: Value) | ||
return a.priority > b.priority | ||
end) | ||
end | ||
|
||
return MockMemoryStoreQueue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
local MockMemoryStoreSortedMap = {} | ||
MockMemoryStoreSortedMap.__index = MockMemoryStoreSortedMap; | ||
|
||
function MockMemoryStoreSortedMap.new(name) | ||
return setmetatable({ | ||
__store = {} | ||
}, MockMemoryStoreSortedMap) | ||
end | ||
|
||
function MockMemoryStoreSortedMap:GetAsync(key) | ||
return self.__store[key].value | ||
end | ||
|
||
function MockMemoryStoreSortedMap:SetAsync(key, value, expiration) | ||
local value = { | ||
value = value, | ||
expiration = tick() + expiration | ||
} | ||
|
||
self.__store[key] = value | ||
return true | ||
end | ||
|
||
function MockMemoryStoreSortedMap:UpdateAsync(key, transformFunction, expiration) | ||
local oldValue = self.__store[key] | ||
|
||
local newValue = transformFunction(if oldValue then oldValue.value else nil) | ||
if newValue ~= nil then | ||
self:SetAsync(key, newValue, tick() + expiration) | ||
return newValue | ||
else | ||
return nil | ||
end | ||
end | ||
|
||
function MockMemoryStoreSortedMap:RemoveAsync(key) | ||
self.__store[key] = nil | ||
end | ||
|
||
local function sortPairsAscending(valueA, valueB) | ||
return utf8.codepoint(valueA[1]) < utf8.codepoint(valueB[1]) | ||
end | ||
|
||
local function sortPairsDescending(valueA, valueB) | ||
return utf8.codepoint(valueA[1]) > utf8.codepoint(valueB[1]) | ||
end | ||
|
||
function MockMemoryStoreSortedMap:GetRangeAsync(direction, count, exclusiveLowerBound, exclusiveUpperBound) | ||
assert(direction ~= nil) | ||
assert(count ~= nil) | ||
|
||
local keyPairs = {} | ||
for key, value in pairs(self.__store) do | ||
table.insert(keyPairs, {key, value}) | ||
end | ||
|
||
if direction == Enum.SortDirection.Ascending then | ||
table.sort(keyPairs, sortPairsAscending) | ||
elseif direction == Enum.SortDirection.Descending then | ||
table.sort(keyPairs, sortPairsDescending) | ||
end | ||
end | ||
|
||
return MockMemoryStoreSortedMap |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
local MockMemoryStoreSortedMap = require(script.MockMemoryStoreSortedMap) | ||
local MockMemoryStoreQueue = require(script.MockMemoryStoreQueue) | ||
|
||
local MockMemoryStoreService = {} | ||
MockMemoryStoreService.__index = MockMemoryStoreService | ||
|
||
function MockMemoryStoreService:GetSortedMap(name: string) | ||
return MockMemoryStoreSortedMap.new(name) | ||
end | ||
|
||
function MockMemoryStoreService:GetQueue(name: string, timeout: number) | ||
return MockMemoryStoreQueue.new(name, timeout) | ||
end | ||
|
||
return MockMemoryStoreService |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import "@rbxts/types"; | ||
/* | ||
Since MockMemoryStoreService is | ||
designed to mock MemoryStoreService, | ||
we can just use its typings. | ||
*/ | ||
declare const MemoryStoreWrapper: MemoryStoreService; | ||
export = MemoryStoreWrapper; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
local MockMemoryStoreServiceModule = script.MockMemoryStoreService | ||
|
||
local shouldUseMock = false | ||
if game.GameId == 0 then | ||
shouldUseMock = true | ||
elseif game:GetService("RunService"):IsStudio() then | ||
local status, message = pcall(function() | ||
-- This will error if current instance has no Studio API access: | ||
game:GetService("MemoryStoreService"):GetSortedMap("__TEST") | ||
end) | ||
if not status and message:find("403", 1, true) then -- HACK | ||
-- Can connect to datastores, but no API access | ||
shouldUseMock = true | ||
end | ||
end | ||
|
||
-- Return the mock or actual service depending on environment: | ||
if shouldUseMock then | ||
warn("INFO: Using MockMemoryStoreService instead of MemoryStoreService") | ||
return require(MockMemoryStoreServiceModule) | ||
else | ||
return game:GetService("MemoryStoreService") | ||
end |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "@rbxts/mockmemorystoreservice", | ||
"version": "1.0.0", | ||
"description": "A wrapper for memory store service to allow testing locally", | ||
"main": "lib/init.lua", | ||
"scripts": { | ||
"test": "rojo build tests.project.json --output tests.rbxl && run-in-roblox --place tests.rbxl --script ./scripts/tests.lua" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"@rbxts/types": "^1.0.569" | ||
}, | ||
"devDependencies": { | ||
"@rbxts/testez": "^0.3.1-ts.7" | ||
} | ||
} |