[test] add device register E2E

This commit is contained in:
Aleksandr Soloshenko 2024-11-24 20:53:52 +07:00 committed by Aleksandr
parent 4ff3a10394
commit 58ed6856d0
10 changed files with 287 additions and 3 deletions

View File

@ -13,10 +13,10 @@ jobs:
uses: actions/checkout@v4
# step 2: set up go
- name: Set up Go 1.22
uses: actions/setup-go@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "1.22"
go-version: stable
# step 3: install dependencies
- name: Install all Go dependencies
@ -26,10 +26,35 @@ jobs:
- name: Run coverage
run: go test -race -coverprofile=coverage.out -covermode=atomic ./...
e2e:
name: E2E
runs-on: ubuntu-latest
steps:
# step 1: checkout repository code
- name: Checkout code into workspace directory
uses: actions/checkout@v4
# step 2: set up go
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
# step 3: start services
- name: Start services
env:
"FCM__CREDENTIALS_JSON": ${{ secrets.FCM__CREDENTIALS_JSON }}
run: docker compose -f test/e2e/docker-compose.yml up -d --build
# step 4: run test
- name: Run e2e tests
run: cd test/e2e && go test .
build:
name: Build
needs:
- test
- e2e
uses: ./.github/workflows/docker-build.yml
with:
app-name: sms-gateway

View File

@ -33,6 +33,7 @@ lint:
test:
go test -race -coverprofile=coverage.out -covermode=atomic ./...
cd test/e2e && go test .
build:
go build -o tmp/$(project_name) ./cmd/$(project_name)

View File

@ -0,0 +1,6 @@
CREATE DATABASE `sms-public`;
CREATE DATABASE `sms-private`;
---
CREATE USER 'sms' @'%' IDENTIFIED BY 'sms';
GRANT ALL PRIVILEGES ON `sms-public`.* TO 'sms' @'%';
GRANT ALL PRIVILEGES ON `sms-private`.* TO 'sms' @'%';

3
test/e2e/data/config.yml Normal file
View File

@ -0,0 +1,3 @@
---
fcm:
credentials_json: "{}"

View File

@ -0,0 +1,71 @@
services:
public:
image: android-sms-gateway/server
build:
context: ../..
dockerfile: ./build/package/Dockerfile
args:
- APP=sms-gateway
environment:
- DEBUG=
- CONFIG_PATH=config.yml
- GOOSE_DBSTRING=sms:sms@tcp(db:3306)/sms
- HTTP__LISTEN=0.0.0.0:3000
- DATABASE__HOST=db
- DATABASE__PORT=3306
- DATABASE__USER=sms
- DATABASE__PASSWORD=sms
- DATABASE__DATABASE=sms-public
- GATEWAY__MODE=public
- FCM__CREDENTIALS_JSON=${FCM__CREDENTIALS_JSON}
ports:
- "3000:3000"
volumes:
- ./data/config.yml:/app/config.yml:ro
restart: 'unless-stopped'
depends_on:
db:
condition: service_healthy
private:
image: android-sms-gateway/server
build:
context: ../..
dockerfile: ./build/package/Dockerfile
args:
- APP=sms-gateway
environment:
- DEBUG=
- CONFIG_PATH=config.yml
- GOOSE_DBSTRING=sms:sms@tcp(db:3306)/sms
- HTTP__LISTEN=0.0.0.0:3000
- DATABASE__HOST=db
- DATABASE__PORT=3306
- DATABASE__USER=sms
- DATABASE__PASSWORD=sms
- DATABASE__DATABASE=sms-private
- GATEWAY__MODE=private
- GATEWAY__PRIVATE_TOKEN=123456789
ports:
- "3001:3000"
volumes:
- ./data/config.yml:/app/config.yml:ro
restart: 'unless-stopped'
depends_on:
db:
condition: service_healthy
db:
image: mariadb:lts
environment:
- MARIADB_ROOT_PASSWORD=root
- MARIADB_AUTO_UPGRADE=1
volumes:
- ./data/10-init.sql:/docker-entrypoint-initdb.d/10-init.sql:ro
restart: 'unless-stopped'
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
start_period: 4s
interval: 4s
timeout: 2s
retries: 3

1
test/e2e/e2e.go Normal file
View File

@ -0,0 +1 @@
package e2e

7
test/e2e/go.mod Normal file
View File

@ -0,0 +1,7 @@
module github.com/android-sms-gateway/server/test/e2e
go 1.22.0
require github.com/go-resty/resty/v2 v2.16.2
require golang.org/x/net v0.27.0 // indirect

6
test/e2e/go.sum Normal file
View File

@ -0,0 +1,6 @@
github.com/go-resty/resty/v2 v2.16.2 h1:CpRqTjIzq/rweXUt9+GxzzQdlkqMdt8Lm/fuK/CAbAg=
github.com/go-resty/resty/v2 v2.16.2/go.mod h1:0fHAoK7JoBy/Ch36N8VFeMsK7xQOHhvWaC3iOktwmIU=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=

68
test/e2e/main_test.go Normal file
View File

@ -0,0 +1,68 @@
package e2e
import (
"fmt"
"log"
"os"
"os/exec"
"testing"
"time"
"github.com/go-resty/resty/v2"
)
const (
PublicURL = "http://localhost:3000/api"
PrivateURL = "http://localhost:3001/api"
)
func isOnline() bool {
for _, v := range []string{PublicURL, PrivateURL} {
_, err := resty.New().
SetBaseURL(v).
SetTimeout(100 * time.Millisecond).
R().
Get("/health")
if err != nil {
log.Println("waiting for health", err)
return false
}
}
return true
}
func TestMain(m *testing.M) {
log.Println("running e2e tests")
if _, ok := os.LookupEnv("CI"); !ok {
if err := exec.Command("docker", "compose", "up", "-d", "--build").Run(); err != nil {
log.Fatal(fmt.Errorf("docker-compose up -d: %w", err))
}
defer func() {
if err := exec.Command("docker", "compose", "down", "-v").Run(); err != nil {
log.Fatal(fmt.Errorf("docker-compose down -v: %w", err))
}
log.Println("e2e tests finished")
}()
}
startedAt := time.Now()
for {
if time.Since(startedAt) > 20*time.Second {
log.Println("timeout")
return
}
if isOnline() {
log.Println("e2e tests started")
break
}
time.Sleep(1 * time.Second)
}
m.Run()
}

96
test/e2e/mobile_test.go Normal file
View File

@ -0,0 +1,96 @@
package e2e
import (
"testing"
"time"
"github.com/go-resty/resty/v2"
)
func makeClient(baseUrl string) *resty.Client {
return resty.New().
SetBaseURL(baseUrl).
SetTimeout(300 * time.Millisecond)
}
func TestPublicDeviceRegister(t *testing.T) {
cases := []struct {
headers map[string]string
expectedStatusCode int
}{
{
headers: map[string]string{
"Authorization": "Bearer 123456789",
},
expectedStatusCode: 201,
},
{
headers: map[string]string{},
expectedStatusCode: 201,
},
{
headers: map[string]string{
"Authorization": "Bearer 987654321",
},
expectedStatusCode: 201,
},
}
client := makeClient(PublicURL + "/mobile/v1/device")
for _, c := range cases {
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(`{"name": "Public Device Name", "pushToken": "token"}`).
SetHeaders(c.headers).
Post("")
if err != nil {
t.Fatal(err)
}
if res.StatusCode() != c.expectedStatusCode {
t.Fatal(res.StatusCode(), res.String())
}
}
}
func TestPrivateDeviceRegister(t *testing.T) {
cases := []struct {
headers map[string]string
expectedStatusCode int
}{
{
headers: map[string]string{
"Authorization": "Bearer 123456789",
},
expectedStatusCode: 201,
},
{
headers: map[string]string{},
expectedStatusCode: 401,
},
{
headers: map[string]string{
"Authorization": "Bearer 987654321",
},
expectedStatusCode: 401,
},
}
client := makeClient(PrivateURL + "/mobile/v1/device")
for _, c := range cases {
res, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(`{"name": "Private Device Name", "pushToken": "token"}`).
SetHeaders(c.headers).
Post("")
if err != nil {
t.Fatal(err)
}
if res.StatusCode() != c.expectedStatusCode {
t.Fatal(res.StatusCode(), res.String())
}
}
}