{"id":15440067,"url":"https://github.com/santhosh-tekuri/fnet","last_synced_at":"2025-03-28T06:41:21.811Z","repository":{"id":141957239,"uuid":"170477874","full_name":"santhosh-tekuri/fnet","owner":"santhosh-tekuri","description":"programmable hosts, firewall, bandwidth to test network failures in unit testing","archived":false,"fork":false,"pushed_at":"2019-04-09T08:28:04.000Z","size":179,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-02T07:27:01.287Z","etag":null,"topics":["bandwidth","clusters","golang","network-failures","split-brain","testing"],"latest_commit_sha":null,"homepage":"","language":"Go","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/santhosh-tekuri.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":"2019-02-13T09:20:23.000Z","updated_at":"2019-04-09T08:28:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"fbf8ce0a-c839-4671-99c2-dabf8da99b03","html_url":"https://github.com/santhosh-tekuri/fnet","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/santhosh-tekuri%2Ffnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santhosh-tekuri%2Ffnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santhosh-tekuri%2Ffnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/santhosh-tekuri%2Ffnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/santhosh-tekuri","download_url":"https://codeload.github.com/santhosh-tekuri/fnet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245984561,"owners_count":20704794,"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":["bandwidth","clusters","golang","network-failures","split-brain","testing"],"created_at":"2024-10-01T19:10:46.051Z","updated_at":"2025-03-28T06:41:21.794Z","avatar_url":"https://github.com/santhosh-tekuri.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"#fnet\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) \n[![GoDoc](https://godoc.org/github.com/santhosh-tekuri/fnet?status.svg)](https://godoc.org/github.com/santhosh-tekuri/fnet)\n[![Go Report Card](https://goreportcard.com/badge/github.com/santhosh-tekuri/fnet)](https://goreportcard.com/report/github.com/santhosh-tekuri/fnet)\n[![Build Status](https://travis-ci.org/santhosh-tekuri/fnet.svg?branch=master)](https://travis-ci.org/santhosh-tekuri/fnet) \n[![codecov.io](https://codecov.io/github/santhosh-tekuri/fnet/coverage.svg?branch=master)](https://codecov.io/github/santhosh-tekuri/fnet?branch=master)\n\nPackage fnet provides programmable firewall, bandwidth to test\nnetwork failures in unit testing.\n\nThis package (fnet stands for fakenet) is intended for use in unit-testing network related failures.\nYour library does not need any dependency on this package for this. only your\ntests need this package as dependency.\n\nThis package simply wraps `net.Listen`, `net.Dial`, `net.Conn` implementation on\n`tcp:localhost`. It enforces firewall/bandwidth before delegating to actual\nimplementation\n\nSome minimal changes needs to be done in your library for this. Consider following\nsimple library code, to demonstrate the changes:\n\n~~~go\npackage myapp\n\ntype Server struct{\n    HostPort string\n    ....\n}\n\nfunc (s *Server) launch() {\n    lr, err := net.Listen(\"tcp\", s.HostPort)\n    ...\n}\n\ntype Client struct{\n    HostPort string\n    ...\n}\n\nfunc (c *client) sendReq(req string) error {\n\tconn, err := net.Dial(\"tcp\", c.HostPort)\n    ...\n}\n~~~\n\nYou have to mock `net.Listen`, `net.Dial` in your code. For this introduce transport interface as shown below:\n\n~~~go\npackage myapp\n\ntype listenFn func(network, address string) (net.Listener, error)\ntype dialFn func(network, address string) (net.Conn, error)\n\ntype Server struct{\n    HostPort string\n    listenFn listenFn // intialize to net.Listen\n    ....\n}\n\nfunc (s *Server) launch() {\n    lr, err := s.listenFn(\"tcp\", s.HostPort)\n    ...\n}\n\ntype Client struct{\n    HostPort string\n    dialFn   dialFn // initialize to net.Dial\n    ...\n}\n\nfunc (c *client) sendReq(req string) error {\n     conn, err := c.dialFn(\"tcp\", c.HostPort)\n     ...\n}\n\n// unit test code ---------------------\n\nfunc TestServer(t *testing.T) {\n    // create network of 3 hosts\n    nw := fnet.New()\n    earth, mars, venus := nw.Host(\"earth\"), nw.Host(\"mars\"), nw.Host(\"venus\")\n\n    s1 := \u0026Server{HostPort: \"earth:80\", listenFn: earth.Listen} // server1 running on earth\n    s2 := \u0026Server{HostPort: \"mars:80\", listenFn: mars.Listen}   // server2 running on mars\n    c := \u0026Client{Servers: []{\"earth:80\", \"mars:80\"}, dialFn: venus.Dial} // client is running on venus\n\n    // make s1 unreachable to client\n    nw.SetFirewall(fnet.Split([]string{\"earth\"}, fnet.AllowAll))\n    if reply, err := c.SendReq(\"hello\"); err!=nil {\n        t.Fatal(\"expected to connect s2\")\n    }\n\n    // now make s2 unreachable to client, but not s1\n    nw.SetFirewall(fnet.Split([]string{\"mars\"}, fnet.AllowAll))\n    if reply, err := c.SendReq(\"hello\"); err!=nil {\n        t.Fatal(\"expected to connect s1\")\n    }\n}\n~~~\nYou can mock `net.Listen`, `net.Dial` and `net.DialTimeout` using this package as shown above\n\nNow you can various network failures as shown above using `fnet.Firewall` `fnet.Bandwidth`\n\n## Firewalls\n\nThis package provides 3 implementations of firewall:\n\n### AllowAll:\n\nThis does not block any network traffic.\nThis is the default firewall set on newly created network.\n\n### AllowSelf:\n\nThis blocks traffic between distinct hosts.\nNote that traffic within the host is allowed.\nConsider network with hosts m1, m2, m3 and m4,\nAllowSelf creates 4 network partitions: m1 | m2 | m3 | m4\n\n### Split:\n\nThis implements network partioning. Mutiple partitions\ncan be defined by chaining. See example below:\n~~~go\n// Consider network with hosts m1, m2, m3, m4, m5 and m6\n\n// 2 partitions: m1 m2 | m3 m4 m5 m6\nfirewall := fnet.Split([]string{\"m1\", \"m2\"}, fnet.AllowAll)\n\n// 3 partitions: m1 m2 | m3 m4 | m5 m6\nfirewall := fnet.Split([]string{\"m1\", \"m2\"}, fnet.AllowAll)\nfirewall = fnet.Split([]string{\"m3\", \"m4\"}, firewall) // chaining\n~~~\nYou can create your own firewall implementation if needed. It is simple single method interface:\n~~~go\ntype Firewall interface {\n    Allow(host1, host2 string) bool\n}\n~~~\n\n## Bandwidth\n\nto set bandwidth between two hosts:\n~~~go\nnw := fnet.New()\nearth, mars := nw.Host(\"earth\"), nw.Host(\"mars\")\nnw.SetBandwidth(\"earth\", \"mars\", fnet.Bandwidth(10*1024*1024)) // 10MB per second between earth and mars\n\n// to revert\nnw.SetBandwidth(\"earth\", \"mars\", fnet.NoLimit)\n~~~","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanthosh-tekuri%2Ffnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsanthosh-tekuri%2Ffnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsanthosh-tekuri%2Ffnet/lists"}