{"id":21847551,"url":"https://github.com/scribd/go-testslapd","last_synced_at":"2025-10-28T12:48:57.321Z","repository":{"id":66239613,"uuid":"221029397","full_name":"scribd/go-testslapd","owner":"scribd","description":"Golang bindings for a dockerized test LDAP server","archived":false,"fork":false,"pushed_at":"2019-11-15T17:08:26.000Z","size":13,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-01-26T12:23:56.465Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scribd.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-11-11T17:03:04.000Z","updated_at":"2019-11-15T17:08:27.000Z","dependencies_parsed_at":"2023-03-31T11:34:30.022Z","dependency_job_id":null,"html_url":"https://github.com/scribd/go-testslapd","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/scribd%2Fgo-testslapd","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scribd%2Fgo-testslapd/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scribd%2Fgo-testslapd/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scribd%2Fgo-testslapd/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scribd","download_url":"https://codeload.github.com/scribd/go-testslapd/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244835574,"owners_count":20518263,"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-11-27T23:18:35.896Z","updated_at":"2025-10-28T12:48:52.290Z","avatar_url":"https://github.com/scribd.png","language":"Go","readme":"# go-ldap-test\n\nA library for testing code against an LDAP directory.\n\nTo the author's knowledge, there does not exist an in-memory LDAP server compatible with OpenLDAP for Golang.  There exist plenty of quality libraries that almost fit the author's needs, but not quite.\n\nSince time was limited, the author did the next best thing and wrote some code to do stand up an LDAP directory via `docker`.\n\nIt's less elegant than a pure code solution would be, but it works, and it allows one to test one's LDAP dependent code against a temporary local directory server- which was the goal.\n\nIn your test code, set up something like this:\n\n\timport \"github.com/scribd/go-testslapd/pkg/testslapd\"\n\t\n    var slapd *testslapd.TestSlapd\n    var ldapSetup bool\n\n    func TestMain(m *testing.M) {\n        setUp()\n\n        code := m.Run()\n\n        tearDown()\n\n        os.Exit(code)\n    }\n\n    // runs before the tests start\n    func setUp() {\n        // start the test server if it's not already running\n        if !ldapSetup {\n            port, err := freeport.GetFreePort()\n            if err != nil {\n                fmt.Printf(\"Error getting free port: %s\\n\", err)\n                os.Exit(1)\n\n            }\n\n            log.Printf(\"Starting LDAP Server on port %d\", port)\n            \n            org := \"scribd\"\n            base := \"dc=scribd,dc=com\"\n            domain := \"scribd.com\"\n            adminPassword := \"letmein\"\n            bindDn := fmt.Sprintf(\"cn=admin,dc=scribd,dc=com\")\n\n            slapd = testslapd.NewTestSlapd(port, org, base, domain, adminPassword, \"\", \"\")\n\n            slapd.SetVerbose(true)\n\n            slapd.SetProvisioner(func() error {\n                l, err := ldap.Dial(\"tcp\", slapd.Address)\n                if err != nil {\n                    fmt.Printf(\"Failed to dial LDAP at %s: %s\", slapd.Address, err)\n                    t.Fail()\n                }\n\n                err = l.Bind(bindDn, adminPassword)\n                if err != nil {\n                    log.Printf(\"--- failed to bind to ldap: %s ---\", err)\n                    return err\n                }\n\n                fmt.Printf(\"--- Running provision function ---\\n\")\n\n                log.Printf(\"--- adding group ou ---\")\n                r := ldap.NewAddRequest(\"ou=group,dc=scribd,dc=com\")\n                r.Attribute(\"ou\", []string{\"group\"})\n                r.Attribute(\"objectClass\", []string{\"top\", \"organizationalUnit\"})\n\n                err = l.Add(r)\n                if err != nil {\n                    log.Printf(\"failed to add group ou to directory: %s\", err)\n                    t.Fail()\n                }\n\n                r = ldap.NewAddRequest(\"ou=users,dc=scribd,dc=com\")\n                r.Attribute(\"ou\", []string{\"users\"})\n                r.Attribute(\"objectClass\", []string{\"top\", \"organizationalUnit\"})\n\n                log.Printf(\"--- adding users ou ---\")\n\n                err = l.Add(r)\n                if err != nil {\n                    log.Printf(\"failed to add users ou to directory: %s\", err)\n                    t.Fail()\n                }\n\n                l.Close()\n\n                fmt.Printf(\"--- End provision function ---\\n\")\n\n                return err\n            })\n\n            err = slapd.StartTestServer()\n            if err != nil {\n                fmt.Printf(\"Failed starting slapd container %q: %s\", slapd.ContainerName, err)\n                log.Fatal(err)\n            }\n\n            err = slapd.Provision()\n            if err != nil {\n                fmt.Printf(\"Failed running provisioner: %s\", err)\n                log.Fatal(err)\n            }\n\n            ldapSetup = true\n        }\n    }\n\n    // runs at the end to clean up\n    func tearDown() {\n        err := slapd.StopTestServer()\n        if err != nil {\n            log.Fatalf(err.Error())\n        }\n    }\n\n    // run a test that connects to the server\n    func TestSomething(t *testing.T)  {\n        l, err := ldap.Dial(\"tcp\", slapd.Address)\n        if err != nil {\n            fmt.Printf(\"Failed to dial LDAP at %s: %s\", slapd.Address, err)\n            t.Fail()\n        }\n\n        err = l.Bind(bindDn, adminPassword)\n        if err != nil {\n            log.Printf(\"--- failed to bind to ldap: %s ---\", err)\n            t.Fail()\n        }\n\n        req := ldap.NewSearchRequest(\n            base,\n            ldap.ScopeWholeSubtree,\n            ldap.NeverDerefAliases,\n            0,\n            0,\n            false,\n            \"(objectClass=top)\",\n                []string{},\n            nil,\n            )\n\n        resp, err := l.Search(req)\n        if err != nil {\n            fmt.Printf(\"Failed searching directory: %s\", err)\n            t.Fail()\n        }\n        assert.True(t, len(resp.Entries) == 4, \"Expected entries in directory\")\n\n        inputs := []struct{\n            name string\n            dn string\n        }{\n            {\n                \"org\",\n                \"dc=scribd,dc=com\",\n            },\n            {\n                \"admin\",\n                \"cn=admin,dc=scribd,dc=com\",\n            },\n            {\n                \"group\",\n                \"ou=group,dc=scribd,dc=com\",\n            },\n            {\n                \"users\",\n                \"ou=users,dc=scribd,dc=com\",\n            },\n        }\n\n        for i, tc := range inputs {\n            t.Run(tc.name, func(t *testing.T){\n                assert.True(t, resp.Entries[i].DN == tc.dn, \"Missing expected DN in directory\")\n            })\n        }\n\n        l.Close()\n    }\n## Caveats\n\n* As currently written, only 1 container can run at a time.  Concurrent tests of multiple projects using this library might encounter name collision on the test container name. \n\n* If your tests panic, you will likely need to clean out the test container manualy via `docker rm -f ldaptest`.  Anything that causes golang to simply stop without running the cleanup code will leave the container running in the background.\n\n* This package does not install `docker` for you.  The `docker` binary is assumed to be already present, in the PATH, and that the user running the tests has access to the `docker` daemon.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscribd%2Fgo-testslapd","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscribd%2Fgo-testslapd","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscribd%2Fgo-testslapd/lists"}