{"id":16701431,"url":"https://github.com/ferd/sups","last_synced_at":"2025-03-21T19:33:16.152Z","repository":{"id":141684018,"uuid":"125574857","full_name":"ferd/sups","owner":"ferd","description":"PropEr model helper library to validate implementations of supervisor trees","archived":false,"fork":false,"pushed_at":"2018-03-16T22:11:17.000Z","size":24,"stargazers_count":65,"open_issues_count":0,"forks_count":1,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-18T04:42:47.605Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Erlang","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ferd.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-16T22:10:09.000Z","updated_at":"2025-02-06T02:01:44.000Z","dependencies_parsed_at":null,"dependency_job_id":"a0ee1417-99a7-4922-995d-327ffc16bcc2","html_url":"https://github.com/ferd/sups","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd%2Fsups","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd%2Fsups/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd%2Fsups/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferd%2Fsups/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ferd","download_url":"https://codeload.github.com/ferd/sups/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244855718,"owners_count":20521693,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-12T18:44:01.719Z","updated_at":"2025-03-21T19:33:16.141Z","avatar_url":"https://github.com/ferd.png","language":"Erlang","funding_links":[],"categories":[],"sub_categories":[],"readme":"sups\r\n=====\r\n\r\nExperimental code library to be used with PropEr or Quickcheck to validate that an OTP application is properly implemented to match the structure of its supervision tree.\r\n\r\nBasically, in a scenario where the supervision structure encodes the expected failure semantics of a program, this library can be used to do fault-injection and failure simulation to see that the failures taking place within the program actually respect the model exposed by the supervision tree. If random process kills or simulated faults end up killing unexpected supervision subtrees, it is assumed that the caller processes have weaknesses in how they handle events.\r\n\r\nThis documentation is still a work in progress.\r\n\r\nCalls\r\n-----\r\n\r\nThe API needs rework to be a bit more transparent. This doc needs rework to be a bit more helpful.\r\n\r\n- `sups_lib:init_state()` and `sups_lib:init_state([WhiteList])`: takes a snapshot of the supervision tree of currently running applications. Should be called before any other function of this library in a PropEr model to give it a baseline data set against which to run.\r\n- `mark_as_dead(State, N, Filters, WhiteList)` where `N` should be an integer picked randomly by the test framework. See the _Filters_ section for filters. This function kills a random process in the supervision tree, and makes guesses (based on the tree structure) as to what processes should be expected to die along with it.\r\n- `mock_success(State, MockFun, UnmockFun, WhiteList)` takes two functions: the first one of the form `fun() -\u003e DoSomeMocking, IntegerValue end`, where you can set up any mocking you want, and `IntegerValue` tells the system how long to sleep (in milliseconds) before calling the unmocking function (`fun() -\u003e Whatever end`), returning the system to normal.\r\n- `validate_mark_as_dead(OldTree, NewTree, DeadList) -\u003e Bool` (TODO: rework to use `State`) can be used as a postcondition to validate that the right processes are living or dead in the application.\r\n- `validate_mock_success(OldTree, NewTree, DeadList) -\u003e Bool` (TODO: rework to use `State`) can be used as a postcondition to validate that no unexpected processes died during fault injection.\r\n\r\nOther functions are exported in `sups_lib` to let you implement custom validation.\r\n\r\nFilters\r\n-------\r\n\r\nZero of more filters can be used in a list:\r\n\r\n- `{named, Atom}`: only kill processes with that given name (in the native registry)\r\n- `{not_named, Atom}`: only kill processes aside from a known named one\r\n- `{tagged, Term}`: only kill processes that have an entry of the form `put(sups_tags, [Term])` in their process dictionary\r\n- `{not_tagged, Term}`: only kill processes that don't have an entry of the form `put(sups_tags, [Term])` in their process dictionary\r\n\r\nHow It Works\r\n------------\r\n\r\nBy building a supervision tree data structure with all annotations, we can create an integer `N` through a regular PropEr or QuickCheck generator that is applied to the tree to denote a specific node. The count starts depth-first, from the right-most child to the leftmost child (meaning that by default shrinking rules, we start by killing newer processes than older and more critical ones).\r\n\r\nThis numeric value is adapted according to filters and whatnot, and since it relies on the shape of the tree rather than the processes it contains, it should allow proper Shrinking to work fine.\r\n\r\nOn a process kill, we analyze the structure of the tree and supervision structure, maintain a list of processes we know should have died, and use it to resolve what the actual tree should be doing as a model.\r\n\r\nExample\r\n-------\r\nTODO\r\n\r\nActually the test code for this lib (`rebar3 proper`)\r\n\r\nCaveats\r\n-------\r\n\r\nCurrently, the system does not track nor model unexpected worker faults in remote subtrees (only local ones), and so those may end up impacting tolerance rates of other supervisors and lower the accuracy of the model. Not too sure if this becomes a problem in practice or not.\r\n\r\nThe system must be running under constant simulation load to be realistic.\r\n\r\nThe sleeping / waiting timer for propagation is a bit ad hoc and requires tweaking\r\n\r\nNot seen enough testing with real world apps.\r\n\r\nRoadmap\r\n-------\r\n\r\n- Fix arguments to functions\r\n- Fix app/demo structure\r\n- Rename mocking functions to be related to fault injection\r\n- Write tests instead of just running them\r\n- See if this holds up in real world projects","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferd%2Fsups","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fferd%2Fsups","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferd%2Fsups/lists"}