mirror of
https://github.com/mochi-mqtt/server.git
synced 2025-09-26 20:21:12 +08:00
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:
43
.github/workflows/build.yml
vendored
Normal file
43
.github/workflows/build.yml
vendored
Normal 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
|
18
.travis.yml
18
.travis.yml
@@ -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)
|
@@ -1,10 +1,11 @@
|
||||
|
||||
<p align="center">
|
||||
|
||||
[](https://travis-ci.com/mochi-co/mqtt)
|
||||
|
||||

|
||||
[](https://github.com/mochi-co/mqtt/issues)
|
||||
[](https://codecov.io/gh/mochi-co/mqtt)
|
||||
[](https://pkg.go.dev/github.com/mochi-co/mqtt)
|
||||
[](https://coveralls.io/github/mochi-co/mqtt?branch=main)
|
||||
[](https://goreportcard.com/report/github.com/mochi-co/mqtt)
|
||||
[](https://pkg.go.dev/github.com/mochi-co/mqtt)
|
||||
|
||||
</p>
|
||||
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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 {
|
||||
|
@@ -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)
|
||||
}
|
||||
|
@@ -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.
|
||||
|
||||
|
@@ -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.
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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.
|
||||
}
|
||||
|
||||
|
@@ -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{
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user