{"id":20450067,"url":"https://github.com/ooni/netem","last_synced_at":"2025-06-27T10:07:00.120Z","repository":{"id":130012998,"uuid":"609231601","full_name":"ooni/netem","owner":"ooni","description":"Network emulation for writing integration tests in Go","archived":false,"fork":false,"pushed_at":"2025-03-19T08:24:45.000Z","size":3371,"stargazers_count":8,"open_issues_count":2,"forks_count":1,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-06-13T20:35:51.467Z","etag":null,"topics":["golang","golang-package","integration-testing","network-emulation","network-performance"],"latest_commit_sha":null,"homepage":"https://ooni.org","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ooni.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","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,"zenodo":null}},"created_at":"2023-03-03T16:45:18.000Z","updated_at":"2025-03-04T01:43:42.000Z","dependencies_parsed_at":"2023-12-19T00:32:16.630Z","dependency_job_id":"8af6e897-de2f-4f5e-9038-957a59150ab4","html_url":"https://github.com/ooni/netem","commit_stats":{"total_commits":91,"total_committers":2,"mean_commits":45.5,"dds":0.01098901098901095,"last_synced_commit":"608dcbcd82b8eabcb675d482e2ca83cf3a41c27d"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ooni/netem","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ooni%2Fnetem","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ooni%2Fnetem/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ooni%2Fnetem/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ooni%2Fnetem/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ooni","download_url":"https://codeload.github.com/ooni/netem/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ooni%2Fnetem/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260508369,"owners_count":23019670,"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":["golang","golang-package","integration-testing","network-emulation","network-performance"],"created_at":"2024-11-15T10:50:08.758Z","updated_at":"2025-06-27T10:07:00.013Z","avatar_url":"https://github.com/ooni.png","language":"Go","readme":"# Netem\n\n[![alltests](https://github.com/ooni/netem/actions/workflows/alltests.yml/badge.svg)](https://github.com/ooni/netem/actions/workflows/alltests.yml) [![GoDoc](https://pkg.go.dev/badge/github.com/ooni/netem/)](https://pkg.go.dev/github.com/ooni/netem) [![Coverage Status](https://coveralls.io/repos/github/ooni/netem/badge.svg?branch=main)](https://coveralls.io/github/ooni/netem?branch=main) [![Slack](https://slack.openobservatory.org/badge.svg)](https://slack.openobservatory.org/)\n\nNetem allows writing integration tests in Go where networking code\nuses [Gvisor](https://gvisor.dev/)-based networking. Netem also\nincludes primitives to emulate link latency, losses, and internet\ncensorship (null routing, SNI-based blocking, throttling). Using\nnetem, one can easily simulate complex integration testing scenarios\ninvolving difficult or adversarial networks.\n\n## Install instructions\n\n_We currently support go1.20_.\n\nTo add netem as a dependency, run:\n\n```console\ngo get -u -v -d github.com/ooni/netem\n```\n\nThis command will download netem and update your `go.mod` and `go.sum`.\n\nYou _probably_ also want to manually force using the [Gvisor](https://gvisor.dev/)\nversion we're using in this library with:\n\n```\ngo get -u -v -d gvisor.dev/gvisor@COMMIT_HASH\n```\n\nbecause [Gvisor](https://gvisor.dev/)'s default branch is not\nready to be used with Go tools and `go get` would misbehave.\n\nWhen updating [Gvisor](https://gvisor.dev/) in this library, make sure\nyou pin to a commit from the [go](https://github.com/google/gvisor/tree/go) branch,\nwhich is the [Gvisor](https://gvisor.dev/) branch supporting go tools.\n\n## Running tests\n\n```console\ngo test .\n```\n\nTo enable the race detector, run:\n\n```console\ngo test -race .\n```\n\n*Note*: we notice that the race detector would be very slow under macOS\nand many tests will fail; it still seems to be fine under Linux.\n\n## Usage\n\nTODO(bassosimone): this section needs to be updated because we have\nrecently removed the `stdlib.go` file and functionality, since we have\nmuch better functionality inside of ooni/probe-cli.\n\nExisting Go code needs to be adjusted to support netem.\n\nSuppose you have this Go code:\n\n```Go\nfunc yourCode(ctx context.Context) error {\n\taddrs, err := net.DefaultResolver.LookupHost(ctx, \"www.example.com\")\n\t// ...\n}\n```\n\nYou need to convert this code to use netem:\n\n```Go\nfunc yourCode(ctx context.Context, nn *netem.Net) error {\n\taddrs, err := nn.LookupHost(ctx, \"www.example.com\")\n\t// ...\n}\n```\n\nNormally, you would create a [netem.Net](\nhttps://pkg.go.dev/github.com/ooni/netem#Net) like this:\n\n```Go\nnn := \u0026netem.Net{\n\tStack: \u0026netem.Stdlib{},\n}\n```\n\nYour code will still work as intended. But, now you have the\noption to replace the `Net` underlying stack with an userspace\nTCP/IP network stack, for writing integration tests.\n\nLet us do that. We start by creating a [StarTopology](\nhttps://pkg.go.dev/github.com/ooni/netem#StarTopology):\n\n```Go\ntopology, err := netem.NewStarTopology(\u0026netem.NullLogger{})\nif err != nil { /* ... */ }\n\ndefer topology.Close()\n```\n\nThen, we use [AddHost](https://pkg.go.dev/github.com/ooni/netem#StarTopology.AddHost)\nto add two userspace network stacks to such a topology:\n\n```Go\nclientStack, err := netem.AddHost(\n\t\"1.2.3.4\",            // stack IPv4 address\n\t\"5.4.3.2\",            // resolver IPv4 address\n\t\u0026netem.LinkConfig{},  // link with no delay, losses, or DPI\n)\nif err != nil { /* ... */ }\n\nserverStack, err := netem.AddHost(\n\t\"5.4.3.2\",            // stack IPv4 address\n\t\"5.4.3.2\",            // resolver IPv4 address\n\t\u0026netem.LinkConfig{},  // link with no delay, losses, or DPI\n)\nif err != nil { /* ... */ }\n```\n\nWe now have the following topology:\n\n```mermaid\ngraph TD\n client[clientStack\u003cbr\u003e1.2.3.4]---router{Router}\n server[serverStack\u003cbr\u003e5.4.3.2]---router\n```\n\nNow, we can create a [DNSServer](\nhttps://pkg.go.dev/github.com/ooni/netem#DNSServer)\non `5.4.3.2` as follows:\n\n```Go\ndnsCfg := netem.NewDNSConfig()\ndnsCfg.AddRecord(\n\t\"www.example.com\",\n\t\"\",                 // empty CNAME\n\t\"5.6.7.8\",\n)\n\ndnsServer, err := netem.NewDNSServer(\n\t\u0026netem.NullLogger{},\n\tserverStack,\n\t\"5.4.3.2\",\n\tdnsCfg,\n)\nif err != nil { /* ... */ }\n```\n\nFinally, we create a [netem.Net](\nhttps://pkg.go.dev/github.com/ooni/netem#Net) as follows:\n\n```Go\nnn2 := \u0026netem.Net{\n\tStack: clientStack,\n}\n```\n\nand we can test `yourCode` as follows:\n\n```Go\nfunc TestYourCode(t *testing.T) {\n\t// ... create nn2 ...\n\terr := yourCode(context.Background(), nn2)\n\tif err != nil {\n\t\tt.Fatal(err)\n\t}\n}\n```\n\nThis test will test your code using the above\nnetwork stacks and topology.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fooni%2Fnetem","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fooni%2Fnetem","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fooni%2Fnetem/lists"}