Replace Travis with Github Actions (#41)

* Remove Travis CI

* Add Github Actions Workflow

* Update badges for build status, coverage, report card, doc reference

* use actions for all pull requests and pushes

* test all files for coverage

* Apply gofmt -s to simplify code

* Fix typos

* Cleanup comments

* Cleanup comments

Co-authored-by: mochi <mochimou@icloud.com>
This commit is contained in:
JB
2022-03-15 19:56:42 +00:00
committed by GitHub
parent 460f0ef681
commit 3286d5a484
19 changed files with 114 additions and 60 deletions

43
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.17
- name: Vet
run: go vet ./...
- name: Test
run: go test -v -race ./...
coverage:
runs-on: ubuntu-latest
steps:
- name: Install Go
if: success()
uses: actions/setup-go@v2
with:
go-version: 1.17.x
- name: Checkout code
uses: actions/checkout@v2
- name: Calc coverage
run: |
go test -v -covermode=count -coverprofile=coverage.out ./...
- name: Convert coverage.out to coverage.lcov
uses: jandelgado/gcov2lcov-action@v1.0.6
- name: Coveralls
uses: coverallsapp/github-action@v1.1.2
with:
github-token: ${{ secrets.github_token }}
path-to-lcov: coverage.lcov

View File

@@ -1,18 +0,0 @@
dist: xenial
language: go
env:
- GO111MODULE=on
go:
- 1.13.x
git:
depth: 1
script:
- go test -v -race ./... -coverprofile=coverage.txt -covermode=atomic
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@@ -1,10 +1,11 @@
<p align="center">
[![Build Status](https://travis-ci.com/mochi-co/mqtt.svg?token=59nqixhtefy2iQRwsPcu&branch=master)](https://travis-ci.com/mochi-co/mqtt)
![build status](https://github.com/mochi-co/mqtt/actions/workflows/build.yml/badge.svg)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/mochi-co/mqtt/issues)
[![codecov](https://codecov.io/gh/mochi-co/mqtt/branch/master/graph/badge.svg?token=6vBUgYVaVB)](https://codecov.io/gh/mochi-co/mqtt)
[![GoDoc](https://godoc.org/github.com/mochi-co/mqtt?status.svg)](https://pkg.go.dev/github.com/mochi-co/mqtt)
[![Coverage Status](https://coveralls.io/repos/github/mochi-co/mqtt/badge.svg?branch=main)](https://coveralls.io/github/mochi-co/mqtt?branch=main)
[![Go Report Card](https://goreportcard.com/badge/github.com/mochi-co/mqtt)](https://goreportcard.com/report/github.com/mochi-co/mqtt)
[![Go Reference](https://pkg.go.dev/badge/github.com/mochi-co/mqtt.svg)](https://pkg.go.dev/github.com/mochi-co/mqtt)
</p>

View File

@@ -46,7 +46,7 @@ func main() {
// Auth is an example auth provider for the server.
type Auth struct{}
// Auth returns true if a username and password are acceptable.
// Authenticate returns true if a username and password are acceptable.
// Auth always returns true.
func (a *Auth) Authenticate(user, password []byte) bool {
return true
@@ -55,8 +55,5 @@ func (a *Auth) Authenticate(user, password []byte) bool {
// ACL returns true if a user has access permissions to read or write on a topic.
// ACL is used to deny access to a specific topic to satisfy Test.test_subscribe_failure.
func (a *Auth) ACL(user []byte, topic string, write bool) bool {
if topic == "test/nosubscribe" {
return false
}
return true
return topic != "test/nosubscribe"
}

View File

@@ -5,14 +5,17 @@ import (
"github.com/mochi-co/mqtt/server/internal/packets"
)
// Events provides callback handlers for different event hooks.
type Events struct {
OnMessage // published message receieved.
OnConnect // client connected.
OnDisconnect // client disconnected.
}
// Packets is an alias for packets.Packet.
type Packet packets.Packet
// Client contains limited information about a connected client.
type Client struct {
ID string
Listener string

View File

@@ -8,13 +8,20 @@ import (
)
var (
DefaultBufferSize int = 1024 * 256 // the default size of the buffer in bytes.
DefaultBlockSize int = 1024 * 8 // the default size per R/W block in bytes.
// DefaultBufferSize is the default size of the buffer in bytes.
DefaultBufferSize int = 1024 * 256
ErrOutOfRange = errors.New("Indexes out of range")
// DefaultBlockSize is the default size per R/W block in bytes.
DefaultBlockSize int = 1024 * 8
// ErrOutOfRange indicates that the index was out of range.
ErrOutOfRange = errors.New("Indexes out of range")
// ErrInsufficientBytes indicates that there were not enough bytes to return.
ErrInsufficientBytes = errors.New("Insufficient bytes to return")
)
// Buffer is a circular buffer for reading and writing messages.
type Buffer struct {
buf []byte // the bytes buffer.
tmp []byte // a temporary buffer.
@@ -77,7 +84,7 @@ func NewBufferFromSlice(block int, buf []byte) *Buffer {
return b
}
// Get will return the tail and head positions of the buffer.
// GetPos will return the tail and head positions of the buffer.
// This method is for use with testing.
func (b *Buffer) GetPos() (int64, int64) {
return atomic.LoadInt64(&b.tail), atomic.LoadInt64(&b.head)

View File

@@ -19,7 +19,7 @@ func NewReader(size, block int) *Reader {
}
}
// NewReaderFromSlice returns a new Circular Reader using a pre-exising
// NewReaderFromSlice returns a new Circular Reader using a pre-existing
// byte slice.
func NewReaderFromSlice(block int, p []byte) *Reader {
b := NewBufferFromSlice(block, p)

View File

@@ -20,7 +20,7 @@ func NewWriter(size, block int) *Writer {
}
}
// NewWriterFromSlice returns a new Circular Writer using a pre-exising
// NewWriterFromSlice returns a new Circular Writer using a pre-existing
// byte slice.
func NewWriterFromSlice(block int, p []byte) *Writer {
b := NewBufferFromSlice(block, p)

View File

@@ -23,7 +23,8 @@ var (
// defaultKeepalive is the default connection keepalive value in seconds.
defaultKeepalive uint16 = 10
ErrConnectionClosed = errors.New("Connection not open")
// ErrConnectionClosed indicates that the connection closed unexpectedly.
ErrConnectionClosed = errors.New("connection closed unexpectedly")
)
// Clients contains a map of the clients known by the broker.
@@ -256,7 +257,7 @@ func (cl *Client) Stop() {
})
}
// readFixedHeader reads in the values of the next packet's fixed header.
// ReadFixedHeader reads in the values of the next packet's fixed header.
func (cl *Client) ReadFixedHeader(fh *packets.FixedHeader) error {
p, err := cl.r.Read(1)
if err != nil {

View File

@@ -729,7 +729,7 @@ func TestInflightGetAll(t *testing.T) {
m := cl.Inflight.GetAll()
o := map[uint16]InflightMessage{
2: InflightMessage{},
2: {},
}
require.Equal(t, o, m)
}

View File

@@ -19,7 +19,7 @@ func (fh *FixedHeader) Encode(buf *bytes.Buffer) {
encodeLength(buf, int64(fh.Remaining))
}
// decode extracts the specification bits from the header byte.
// Decode extracts the specification bits from the header byte.
func (fh *FixedHeader) Decode(headerByte byte) error {
fh.Type = headerByte >> 4 // Get the message type from the first 4 bytes.

View File

@@ -74,7 +74,7 @@ func TestConnectDecode(t *testing.T) {
}
require.Equal(t, uint8(1), Connect, "Incorrect Packet Type [i:%d] %s", i, wanted.desc)
require.Equal(t, true, (len(wanted.rawBytes) > 2), "Insufficent bytes in packet [i:%d] %s", i, wanted.desc)
require.Equal(t, true, (len(wanted.rawBytes) > 2), "Insufficient bytes in packet [i:%d] %s", i, wanted.desc)
pk := &Packet{FixedHeader: FixedHeader{Type: Connect}}
err := pk.ConnectDecode(wanted.rawBytes[2:]) // Unpack skips fixedheader.

View File

@@ -113,7 +113,7 @@ func TestRetainMessage(t *testing.T) {
require.Equal(t, pk2, index.Root.Leaves["path"].Leaves["to"].Leaves["another"].Leaves["mqtt"].Message)
require.Contains(t, index.Root.Leaves["path"].Leaves["to"].Leaves["another"].Leaves["mqtt"].Clients, "client-1")
q = index.RetainMessage(pk2) // already exsiting
q = index.RetainMessage(pk2) // already existing
require.Equal(t, int64(0), q)
require.NotNil(t, index.Root.Leaves["path"].Leaves["to"].Leaves["another"].Leaves["mqtt"])
require.Equal(t, pk2, index.Root.Leaves["path"].Leaves["to"].Leaves["another"].Leaves["mqtt"].Message)

View File

@@ -3,7 +3,7 @@ package auth
// Allow is an auth controller which allows access to all connections and topics.
type Allow struct{}
// Auth returns true if a username and password are acceptable. Allow always
// Authenticate returns true if a username and password are acceptable. Allow always
// returns true.
func (a *Allow) Authenticate(user, password []byte) bool {
return true
@@ -18,7 +18,7 @@ func (a *Allow) ACL(user []byte, topic string, write bool) bool {
// Disallow is an auth controller which disallows access to all connections and topics.
type Disallow struct{}
// Auth returns true if a username and password are acceptable. Disallow always
// Authenticate returns true if a username and password are acceptable. Disallow always
// returns false.
func (d *Disallow) Authenticate(user, password []byte) bool {
return false

View File

@@ -49,7 +49,7 @@ func (l *MockListener) Serve(establisher EstablishFunc) {
}
}
// SetConfig sets the configuration values of the mock listener.
// Listen begins listening for incoming traffic.
func (l *MockListener) Listen(s *system.Info) error {
if l.ErrListen {
return fmt.Errorf("listen failure")
@@ -92,7 +92,7 @@ func (l *MockListener) IsServing() bool {
return l.Serving
}
// IsServing indicates whether the mock listener is listening.
// IsListening indicates whether the mock listener is listening.
func (l *MockListener) IsListening() bool {
l.Lock()
defer l.Unlock()

View File

@@ -17,6 +17,7 @@ import (
)
var (
// ErrInvalidMessage indicates that a message payload was not valid.
ErrInvalidMessage = errors.New("message type not binary")
// wsUpgrader is used to upgrade the incoming http/tcp connection to a
@@ -34,7 +35,7 @@ type Websocket struct {
address string // the network address to bind to.
config *Config // configuration values for the listener.
listen *http.Server // an http server for serving websocket connections.
establish EstablishFunc // the server's establish conection handler.
establish EstablishFunc // the server's establish connection handler.
end uint32 // ensure the close methods are only called once.
}

View File

@@ -7,11 +7,21 @@ import (
)
const (
// KSubscription is the key for subscription data.
KSubscription = "sub"
KServerInfo = "srv"
KRetained = "ret"
KInflight = "ifm"
KClient = "cl"
// KServerInfo is the key for server info data.
KServerInfo = "srv"
// KRetained is the key for retained messages data.
KRetained = "ret"
// KInflight is the key for inflight messages data.
KInflight = "ifm"
// KClient is the key for client data.
KClient = "cl"
)
// Store is an interface which details a persistent storage connector.
@@ -197,7 +207,7 @@ func (s *MockStore) ReadSubscriptions() (v []Subscription, err error) {
}
return []Subscription{
Subscription{
{
ID: "test:a/b/c",
Client: "test",
Filter: "a/b/c",
@@ -214,7 +224,7 @@ func (s *MockStore) ReadClients() (v []Client, err error) {
}
return []Client{
Client{
{
ID: "cl_client1",
ClientID: "client1",
T: KClient,
@@ -230,7 +240,7 @@ func (s *MockStore) ReadInflight() (v []Message, err error) {
}
return []Message{
Message{
{
ID: "client1_if_100",
T: KInflight,
Client: "client1",
@@ -250,7 +260,7 @@ func (s *MockStore) ReadRetained() (v []Message, err error) {
}
return []Message{
Message{
{
ID: "client1_ret_200",
T: KRetained,
FixedHeader: FixedHeader{

View File

@@ -1,4 +1,4 @@
// packet server provides a MQTT 3.1.1 compliant MQTT server.
// package server provides a MQTT 3.1.1 compliant MQTT server.
package server
import (
@@ -22,14 +22,23 @@ import (
)
const (
Version = "1.1.1" // the server version.
// Version indicates the current server version.
Version = "1.1.1"
)
var (
ErrListenerIDExists = errors.New("Listener id already exists")
ErrReadConnectInvalid = errors.New("Connect packet was not valid")
ErrConnectNotAuthorized = errors.New("Connect packet was not authorized")
ErrInvalidTopic = errors.New("Cannot publish to $ and $SYS topics")
// ErrListenerIDExists indicates that a listener with the same id already exists.
ErrListenerIDExists = errors.New("listener id already exists")
// ErrReadConnectInvalid indicates that the connection packet was invalid.
ErrReadConnectInvalid = errors.New("connect packet was not valid")
// ErrConnectNotAuthorized indicates that the connection packet had incorrect
// authentication parameters.
ErrConnectNotAuthorized = errors.New("connect packet was not authorized")
// ErrInvalidTopic indicates that the specified topic was not valid.
ErrInvalidTopic = errors.New("cannot publish to $ and $SYS topics")
// SysTopicInterval is the number of milliseconds between $SYS topic publishes.
SysTopicInterval time.Duration = 30000

View File

@@ -1882,13 +1882,13 @@ func TestServerLoadClients(t *testing.T) {
require.NotNil(t, s)
clients := []persistence.Client{
persistence.Client{
{
ID: "cl_client1",
ClientID: "client1",
T: persistence.KClient,
Listener: "tcp1",
},
persistence.Client{
{
ID: "cl_client2",
ClientID: "client2",
T: persistence.KClient,