Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Testing: Add a mocking cli & lib #7

Merged
merged 4 commits into from
Jan 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Corde is also actively used to rewrite and develop another discord bot of mine c

Having used most go discord libs available, I wanted something very lightweight yet high-level, that could just run on a lambda without state, caching or long start-up times.

Corde has a single dependency as of yet, and it's just a codegen utility.
Corde has a single dependency as of yet, a radix tree for routing purposes.

The common libs out there didn't really fit that purpose, and neither did they implement the webhook callback API available.

Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ module github.com/Karitham/corde

go 1.18

require github.com/karitham/go-genial v0.2.0

require github.com/akrennmair/go-radix v1.0.1-0.20211215212324-49d05194b0a3

require github.com/matryer/is v1.4.0
require (
github.com/akrennmair/go-radix v1.0.1-0.20211215212324-49d05194b0a3
github.com/karitham/go-genial v0.2.0
github.com/matryer/is v1.4.0
)
8 changes: 4 additions & 4 deletions interactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,10 @@ type Member struct {
Avatar Hash `json:"avatar,omitempty"`
Joined Timestamp `json:"joined_at"`
BoostedSince Timestamp `json:"premium_since,omitempty"`
CommunicationDisabledUntil Timestamp `json:"communication_disabled_until"`
Deaf bool `json:"deaf"`
Mute bool `json:"mute"`
IsPending bool `json:"pending"`
CommunicationDisabledUntil Timestamp `json:"communication_disabled_until,omitempty"`
Deaf bool `json:"deaf,omitempty"`
Mute bool `json:"mute,omitempty"`
IsPending bool `json:"pending,omitempty"`
}

// User is a Discord User
Expand Down
119 changes: 119 additions & 0 deletions owmock/http.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package owmock

import (
"bytes"
"crypto/ed25519"
"encoding/hex"
"encoding/json"
"errors"
"log"
"net/http"
"reflect"
"strconv"
"time"

"github.com/matryer/is"
)

// req makes a defined request to the given uri
func req(c Doer, method string, url string, buf *bytes.Buffer, privK ed25519.PrivateKey) (json.RawMessage, error) {
timestamp := strconv.FormatInt(time.Now().Unix(), 10)

req, _ := http.NewRequest(method, url, buf)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Accept", "application/json")
req.Header.Set("X-Signature-Timestamp", timestamp)
sig := ed25519.Sign(privK, []byte(timestamp+buf.String()))
req.Header.Set("X-Signature-Ed25519", hex.EncodeToString(sig))

resp, err := c.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.ContentLength == 0 {
return nil, nil
}

if resp.StatusCode != http.StatusOK {
return nil, errors.New("status code: " + strconv.Itoa(resp.StatusCode))
}

respBody := json.RawMessage{}
if err = json.NewDecoder(resp.Body).Decode(&respBody); err != nil {
return nil, err
}

log.Println(string(respBody))
return respBody, nil
}

// Doer makes requests
type Doer interface {
Do(*http.Request) (*http.Response, error)
}

// Requester makes requests to the mock endpoint
type Requester struct {
Client Doer
URL string
PrivateKey ed25519.PrivateKey
}

// New returns a new mock requester
func New(endpointURL string) *Requester {
_, priv := GenerateKeys()
v, _ := hex.DecodeString(priv)

return &Requester{
Client: &http.Client{Timeout: 10 * time.Second},
URL: endpointURL,
PrivateKey: v,
}
}

// NewWithClient returns a new mock requester with a default client
func NewWithClient(endpointURL string, c Doer) *Requester {
_, priv := GenerateKeys()
v, err := hex.DecodeString(priv)
if err != nil {
panic(err)
}
return &Requester{
Client: c,
PrivateKey: v,
URL: endpointURL,
}
}

// PostJSON makes a POST request to the endpoint with the given body marshalled
func (r *Requester) PostJSON(body any) (json.RawMessage, error) {
buf := &bytes.Buffer{}
if err := json.NewEncoder(buf).Encode(body); err != nil {
return nil, err
}
return req(r.Client, http.MethodPost, r.URL, buf, r.PrivateKey)
}

// PostJSON makes a POST request to the endpoint with the given body
func (r *Requester) Post(body string) (json.RawMessage, error) {
buf := bytes.NewBufferString(body)
return req(r.Client, http.MethodPost, r.URL, buf, r.PrivateKey)
}

// PostExpect posts a payload and expects a response with the given body
func (r *Requester) PostExpect(t is.T, body any, expectV any) error {
is := is.New(t)
resp, err := r.PostJSON(body)
is.NoErr(err)

typ := reflect.TypeOf(expectV)
respV := reflect.New(typ).Interface()

err = json.Unmarshal(resp, respV)
is.NoErr(err)

is.Equal(respV, expectV)
return nil
}
20 changes: 20 additions & 0 deletions owmock/keys.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package owmock

import (
"bytes"
"crypto/ed25519"
"encoding/hex"
)

// GenerateKeys generates a new keypair of hex-encoded keys
// They shouldn't change between runs, but there's a generator just in case
//
// PubK:
// 2f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee
//
// PrivK:
// 31323334353637383930313233343536373839303132333435363738393031322f8c6129d816cf51c374bc7f08c3e63ed156cf78aefb4a6550d97b87997977ee
func GenerateKeys() (pub string, priv string) {
pubK, privK, _ := ed25519.GenerateKey(bytes.NewBufferString("12345678901234567890123456789012"))
return hex.EncodeToString(pubK), hex.EncodeToString(privK)
}
Loading