Skip to content

Commit

Permalink
Grand test fixup (#138)
Browse files Browse the repository at this point in the history
* start fixing up tests

* fix up tests + automate with drone

* fiddle with linting

* messing about with drone.yml

* some more fiddling

* hmmm

* add cache

* add vendor directory

* verbose

* ci updates

* update some little things

* update sig
  • Loading branch information
tsmethurst authored Aug 12, 2021
1 parent 329a5e8 commit 98263a7
Show file tree
Hide file tree
Showing 2,677 changed files with 1,090,869 additions and 219 deletions.
67 changes: 52 additions & 15 deletions .drone.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,55 @@
---
### Drone configuration file for GoToSocial.
### Connects to https://drone.superseriousbusiness.org to perform testing, linting, and automatic builds/pushes to docker.
###
### For documentation on drone, see: https://docs.drone.io/
### For documentation on drone docker pipelines in particular: https://docs.drone.io/pipeline/docker/overview/

kind: pipeline
type: docker
name: dockerpublish
name: default
steps:
- name: publish image
image: plugins/docker
settings:
auto_tag: true
username:
from_secret: gts_docker_username
password:
from_secret: gts_docker_password
repo: superseriousbusiness/gotosocial
tags: latest
when:
event:
exclude:
- pull_request

# We use golangci-lint for linting.
# See: https://golangci-lint.run/
- name: lint
image: golangci/golangci-lint:v1.41.1
commands:
- golangci-lint run --timeout 5m0s --tests=false --verbose

- name: test
image: golang:1.16.4
environment:
GTS_DB_ADDRESS: postgres
commands:
# `-count 1` => run all tests at least once
# `-p 1` => run maximum one test at a time
# `./...` => run all tests
- go test -count 1 -p 1 ./...

- name: publish
image: plugins/docker
settings:
auto_tag: true
username: gotosocial
password:
from_secret: gts_docker_password
repo: superseriousbusiness/gotosocial
tags: latest
when:
event:
exclude:
- pull_request

services:
# We need this postgres service running for the test step.
# See: https://docs.drone.io/pipeline/docker/syntax/services/
- name: postgres
image: postgres
environment:
POSTGRES_PASSWORD: postgres
---
kind: signature
hmac: 78dd20d97444a9e2904552d56eb52f43ad30ba27e1d897a5ea6808971f9a0ae2

...
37 changes: 0 additions & 37 deletions .github/workflows/golangci-lint.yml

This file was deleted.

36 changes: 33 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ Check the [issues](https://github.com/superseriousbusiness/gotosocial/issues) to

## Communications

Before starting on something, please comment on an issue to say that you're working on it, and send a message to `@[email protected]` (Mastodon) to let them know.

You can also drop into the GoToSocial Matrix room [here](https://matrix.to/#/!mdShFtfScQvVSmjIKX:ondergrond.org?via=ondergrond.org).
Before starting on something, please comment on an issue to say that you're working on it, and/or drop into the GoToSocial Matrix room [here](https://matrix.to/#/#gotosocial:superseriousbusiness.org).

This is the recommended way of keeping in touch with other developers, asking direct questions about code, and letting everyone know what you're up to.

Expand All @@ -36,6 +34,38 @@ If there are no errors, great, you're good to go!

To work with the stylesheet for templates, you need [Node.js](https://nodejs.org/en/download/), then run `yarn install` in `web/source/`. Recompiling the bundle.css is `node build.js` but can be automated with [nodemon](https://www.npmjs.com/package/nodemon) on file change: `nodemon -w style.css build.js`.

### Golang forking quirks

One of the quirks of Golang is that it relies on the source management path being the same as the one used within `go.mod` and in package imports within individual Go files. This makes working with forks a bit awkward.

Let's say you fork GoToSocial to `github.com/yourgithubname/gotosocial`, and then clone that repository to `~/go/src/github.com/yourgithubname/gotosocial`. You will probably run into errors trying to run tests or build, so you might change your `go.mod` file so that the module is called `github.com/yourgithubname/gotosocial` instead of `github.com/superseriousbusiness/gotosocial`. But then this breaks all the imports within the project. Nightmare! So now you have to go through the source files and painstakingly replace `github.com/superseriousbusiness/gotosocial` with `github.com/yourgithubname/gotosocial`. This works OK, but when you decide to make a pull request against the original repo, all the changed paths are included! Argh!

The correct solution to this is to fork, then clone the upstream repository, then set `origin` of the upstream repository to that of your fork.

See [this blogpost](https://blog.sgmansfield.com/2016/06/working-with-forks-in-go/) for more details.

In case this post disappears, here are the steps (slightly modified):

>
> Pull the original package from the canonical place with the standard go get command:
>
> `go get github.com/superseriousbusiness/gotosocial`
>
> Fork the repository on Github or set up whatever other remote git repo you will be using. In this case, I would go to Github and fork the repository.
>
> Navigate to the top level of the repository on your computer. Note that this might not be the specific package you’re using:
>
> `cd $GOPATH/src/github.com/superseriousbusiness/gotosocial`
>
> Rename the current origin remote to upstream:
>
> `git remote rename origin upstream`
>
> Add your fork as origin:
>
> `git remote add origin [email protected]/yourgithubname/gotosocial`
>
## Setting up your test environment

GoToSocial provides a [testrig](https://github.com/superseriousbusiness/gotosocial/tree/main/testrig) with a bunch of mock packages you can use in integration tests.
Expand Down
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ ADD cmd /go/src/github.com/superseriousbusiness/gotosocial/cmd
ADD internal /go/src/github.com/superseriousbusiness/gotosocial/internal
ADD testrig /go/src/github.com/superseriousbusiness/gotosocial/testrig
ADD docs/swagger.go /go/src/github.com/superseriousbusiness/gotosocial/docs/swagger.go

# dependencies and vendor
ADD go.mod /go/src/github.com/superseriousbusiness/gotosocial/go.mod
ADD go.sum /go/src/github.com/superseriousbusiness/gotosocial/go.sum
ADD vendor /go/src/github.com/superseriousbusiness/gotosocial/vendor

# move .git dir and version for versioning
ADD .git /go/src/github.com/superseriousbusiness/gotosocial/.git
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ Proper documentation for running and maintaining GoToSocial will be forthcoming

For now (if you want to run it pre-alpha, like a beast), check out the [quick and dirty getting started guide](https://docs.gotosocial.org/en/latest/installation_guide/quick_and_dirty/).

## Contributing

You wanna contribute to GtS? Great! ❤️❤️❤️ Check out the issues page to see if there's anything you wanna jump in on, and read the [CONTRIBUTING.md](./CONTRIBUTING.md) file for guidelines and setting up your dev environment.

## Contact

For questions and comments, you can [join our Matrix channel](https://matrix.to/#/#gotosocial:superseriousbusiness.org) at `#gotosocial:superseriousbusiness.org`. This is the quickest way to reach the devs. You can also mail [[email protected]](mailto:[email protected]).
Expand Down
2 changes: 1 addition & 1 deletion internal/api/client/media/mediacreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func (suite *MediaCreateTestSuite) TestStatusCreatePOSTImageHandlerSuccessful()
}

// check response
suite.EqualValues(http.StatusAccepted, recorder.Code)
suite.EqualValues(http.StatusOK, recorder.Code)

result := recorder.Result()
defer result.Body.Close()
Expand Down
20 changes: 9 additions & 11 deletions internal/api/client/status/statuscreate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,13 @@ func (suite *StatusCreateTestSuite) TestPostNewStatus() {
ctx.Set(oauth.SessionAuthorizedAccount, suite.testAccounts["local_account_1"])
ctx.Request = httptest.NewRequest(http.MethodPost, fmt.Sprintf("http://localhost:8080/%s", status.BasePath), nil) // the endpoint we're hitting
ctx.Request.Form = url.Values{
"status": {"this is a brand new status! #helloworld"},
"spoiler_text": {"hello hello"},
"sensitive": {"true"},
"visibility_advanced": {"mutuals_only"},
"likeable": {"false"},
"replyable": {"false"},
"federated": {"false"},
"status": {"this is a brand new status! #helloworld"},
"spoiler_text": {"hello hello"},
"sensitive": {"true"},
"visibility": {string(model.VisibilityMutualsOnly)},
"likeable": {"false"},
"replyable": {"false"},
"federated": {"false"},
}
suite.statusModule.StatusCreatePOSTHandler(ctx)

Expand All @@ -120,7 +120,7 @@ func (suite *StatusCreateTestSuite) TestPostNewStatus() {
assert.Equal(suite.T(), "hello hello", statusReply.SpoilerText)
assert.Equal(suite.T(), "<p>this is a brand new status! <a href=\"http://localhost:8080/tags/helloworld\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>helloworld</span></a></p>", statusReply.Content)
assert.True(suite.T(), statusReply.Sensitive)
assert.Equal(suite.T(), model.VisibilityPrivate, statusReply.Visibility)
assert.Equal(suite.T(), model.VisibilityPrivate, statusReply.Visibility) // even though we set this status to mutuals only, it should serialize to private, because masto has no idea about mutuals_only
assert.Len(suite.T(), statusReply.Tags, 1)
assert.Equal(suite.T(), model.Tag{
Name: "helloworld",
Expand Down Expand Up @@ -161,13 +161,11 @@ func (suite *StatusCreateTestSuite) TestPostAnotherNewStatus() {
b, err := ioutil.ReadAll(result.Body)
assert.NoError(suite.T(), err)

fmt.Println(string(b))

statusReply := &model.Status{}
err = json.Unmarshal(b, statusReply)
assert.NoError(suite.T(), err)

assert.Equal(suite.T(), "<p><a href=\"http://localhost:8080/tags/test\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>test</span></a> alright, should be able to post <a href=\"http://localhost:8080/tags/links\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>links</span></a> with fragments in them now, let&#39;s see........<br/><br/><a href=\"https://docs.gotosocial.org/en/latest/user_guide/posts/#links\" rel=\"noopener nofollow noreferrer\" target=\"_blank\">docs.gotosocial.org/en/latest/user_guide/posts/#links</a><br/><a href=\"http://localhost:8080/tags/gotosocial\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\">#<span>gotosocial</span></a><br/><br/>(tobi remember to pull the docker image challenge)</p>", statusReply.Content)
assert.Equal(suite.T(), "\u003cp\u003e\u003ca href=\"http://localhost:8080/tags/test\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\"\u003e#\u003cspan\u003etest\u003c/span\u003e\u003c/a\u003e alright, should be able to post \u003ca href=\"http://localhost:8080/tags/links\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\"\u003e#\u003cspan\u003elinks\u003c/span\u003e\u003c/a\u003e with fragments in them now, let\u0026#39;s see........\u003cbr/\u003e\u003cbr/\u003e\u003ca href=\"https://docs.gotosocial.org/en/latest/user_guide/posts/#links\" rel=\"noopener nofollow noreferrer\" target=\"_blank\"\u003edocs.gotosocial.org/en/latest/user_guide/posts/#links\u003c/a\u003e\u003cbr/\u003e\u003cbr/\u003e\u003ca href=\"http://localhost:8080/tags/gotosocial\" class=\"mention hashtag\" rel=\"tag nofollow noreferrer noopener\" target=\"_blank\"\u003e#\u003cspan\u003egotosocial\u003c/span\u003e\u003c/a\u003e\u003cbr/\u003e\u003cbr/\u003e(tobi remember to pull the docker image challenge)\u003c/p\u003e", statusReply.Content)
}

func (suite *StatusCreateTestSuite) TestPostNewStatusWithEmoji() {
Expand Down
63 changes: 13 additions & 50 deletions internal/federation/federator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,13 @@
package federation_test

import (
"bytes"
"context"
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/go-fed/activity/pub"
"github.com/go-fed/httpsig"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/suite"
Expand Down Expand Up @@ -117,63 +112,31 @@ func (suite *ProtocolTestSuite) TestAuthenticatePostInbox() {
sendingAccount := suite.accounts["remote_account_1"]
inboxAccount := suite.accounts["local_account_1"]

encodedPublicKey, err := x509.MarshalPKIXPublicKey(sendingAccount.PublicKey)
assert.NoError(suite.T(), err)
publicKeyBytes := pem.EncodeToMemory(&pem.Block{
Type: "PUBLIC KEY",
Bytes: encodedPublicKey,
})
publicKeyString := strings.ReplaceAll(string(publicKeyBytes), "\n", "\\n")

// for this test we need the client to return the public key of the activity creator on the 'remote' instance
responseBodyString := fmt.Sprintf(`
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://w3id.org/security/v1"
],
"id": "%s",
"type": "Person",
"preferredUsername": "%s",
"inbox": "%s",
"publicKey": {
"id": "%s",
"owner": "%s",
"publicKeyPem": "%s"
}
}`, sendingAccount.URI, sendingAccount.Username, sendingAccount.InboxURI, sendingAccount.PublicKeyURI, sendingAccount.URI, publicKeyString)

// create a transport controller whose client will just return the response body string we specified above
tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(func(req *http.Request) (*http.Response, error) {
r := ioutil.NopCloser(bytes.NewReader([]byte(responseBodyString)))
return &http.Response{
StatusCode: 200,
Body: r,
}, nil
}), suite.db)

tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db)
// now setup module being tested, with the mock transport controller
federator := federation.NewFederator(suite.db, testrig.NewTestFederatingDB(suite.db), tc, suite.config, suite.log, suite.typeConverter, testrig.NewTestMediaHandler(suite.db, suite.storage))

// setup request
request := httptest.NewRequest(http.MethodPost, "http://localhost:8080/users/the_mighty_zork/inbox", nil)
// we need these headers for the request to be validated
request.Header.Set("Signature", activity.SignatureHeader)
request.Header.Set("Date", activity.DateHeader)
request.Header.Set("Digest", activity.DigestHeader)

verifier, err := httpsig.NewVerifier(request)
assert.NoError(suite.T(), err)

ctx := context.Background()
// by the time AuthenticatePostInbox is called, PostInboxRequestBodyHook should have already been called,
// which should have set the account and username onto the request. We can replicate that behavior here:
ctxWithAccount := context.WithValue(ctx, util.APAccount, inboxAccount)
ctxWithActivity := context.WithValue(ctxWithAccount, util.APActivity, activity)
ctxWithVerifier := context.WithValue(ctxWithActivity, util.APRequestingPublicKeyVerifier, verifier)

request := httptest.NewRequest(http.MethodPost, "http://localhost:8080/users/the_mighty_zork/inbox", nil) // the endpoint we're hitting
// we need these headers for the request to be validated
request.Header.Set("Signature", activity.SignatureHeader)
request.Header.Set("Date", activity.DateHeader)
request.Header.Set("Digest", activity.DigestHeader)
// we can pass this recorder as a writer and read it back after
recorder := httptest.NewRecorder()

// trigger the function being tested, and return the new context it creates
newContext, authed, err := federator.AuthenticatePostInbox(ctxWithActivity, recorder, request)
newContext, authed, err := federator.AuthenticatePostInbox(ctxWithVerifier, recorder, request)
assert.NoError(suite.T(), err)
assert.True(suite.T(), authed)

Expand Down
Loading

0 comments on commit 98263a7

Please sign in to comment.