Documentation
¶
Overview ¶
SPDX-License-Identifier: AGPL-3.0-or-later DMRHub - Run a DMR network server in a single binary Copyright (C) 2023-2026 Jacob McSwain
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
The source code is available at <https://github.com/USA-RedDragon/DMRHub>
Index ¶
- Variables
- func CreateAndLoginUser(t *testing.T, router *gin.Engine, user apimodels.UserRegistration) (APIResponse, *httptest.ResponseRecorder, CookieJar)
- func CreateScheduledNet(t *testing.T, router *gin.Engine, jar CookieJar, ...) (apimodels.ScheduledNetResponse, *httptest.ResponseRecorder)
- func DeleteScheduledNet(t *testing.T, router *gin.Engine, jar CookieJar, id uint) *httptest.ResponseRecorder
- func ExportNetCheckIns(t *testing.T, router *gin.Engine, jar CookieJar, netID uint, format string) *httptest.ResponseRecorder
- func GetNet(t *testing.T, router *gin.Engine, jar CookieJar, netID uint) (apimodels.NetResponse, *httptest.ResponseRecorder)
- func GetNetCheckIns(t *testing.T, router *gin.Engine, jar CookieJar, netID uint) (*httptest.ResponseRecorder, []byte)
- func GetPeer(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (models.Peer, *httptest.ResponseRecorder)
- func GetRepeater(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (models.Repeater, *httptest.ResponseRecorder)
- func GetTalkgroup(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (models.Talkgroup, *httptest.ResponseRecorder)
- func GetUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (models.User, *httptest.ResponseRecorder)
- func GetUserMe(t *testing.T, router *gin.Engine, jar CookieJar) (models.User, *httptest.ResponseRecorder)
- func ListNets(t *testing.T, router *gin.Engine, jar CookieJar, queryParams string) (*httptest.ResponseRecorder, []byte)
- func LoginAdmin(t *testing.T, router *gin.Engine) (APIResponse, *httptest.ResponseRecorder, CookieJar)
- func LoginUser(t *testing.T, router *gin.Engine, user apimodels.AuthLogin) (APIResponse, *httptest.ResponseRecorder, CookieJar)
- func PatchNet(t *testing.T, router *gin.Engine, jar CookieJar, netID uint, ...) (apimodels.NetResponse, *httptest.ResponseRecorder)
- func PatchPeer(t *testing.T, router *gin.Engine, id uint, jar CookieJar, ...) (models.Peer, *httptest.ResponseRecorder)
- func StartNet(t *testing.T, router *gin.Engine, jar CookieJar, body apimodels.NetStartPost) (apimodels.NetResponse, *httptest.ResponseRecorder)
- func StopNet(t *testing.T, router *gin.Engine, jar CookieJar, netID uint) (apimodels.NetResponse, *httptest.ResponseRecorder)
- type APIResponse
- func ApproveUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func CreateTalkgroup(t *testing.T, router *gin.Engine, jar CookieJar, tg apimodels.TalkgroupPost) (APIResponse, *httptest.ResponseRecorder)
- func DeletePeer(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func DeletePeerRule(t *testing.T, router *gin.Engine, peerID uint, ruleID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func DeleteRepeater(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func DeleteTalkgroup(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func DeleteUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func DemoteUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func LinkRepeater(t *testing.T, router *gin.Engine, id uint, linkType string, slot string, ...) (APIResponse, *httptest.ResponseRecorder)
- func LogoutUser(t *testing.T, router *gin.Engine, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func PatchRepeater(t *testing.T, router *gin.Engine, id uint, jar CookieJar, ...) (APIResponse, *httptest.ResponseRecorder)
- func PatchTalkgroup(t *testing.T, router *gin.Engine, id uint, jar CookieJar, ...) (APIResponse, *httptest.ResponseRecorder)
- func PatchUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar, ...) (APIResponse, *httptest.ResponseRecorder)
- func PromoteUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func RegisterUser(t *testing.T, router *gin.Engine, user apimodels.UserRegistration) (APIResponse, *httptest.ResponseRecorder)
- func SetRepeaterTalkgroups(t *testing.T, router *gin.Engine, id uint, jar CookieJar, ...) (APIResponse, *httptest.ResponseRecorder)
- func SetTalkgroupAdmins(t *testing.T, router *gin.Engine, id uint, jar CookieJar, ...) (APIResponse, *httptest.ResponseRecorder)
- func SetTalkgroupNCOs(t *testing.T, router *gin.Engine, id uint, jar CookieJar, ...) (APIResponse, *httptest.ResponseRecorder)
- func SuspendUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- func UnlinkRepeater(t *testing.T, router *gin.Engine, id uint, linkType string, slot string, ...) (APIResponse, *httptest.ResponseRecorder)
- func UnsuspendUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
- type APIResponseUserList
- type Backend
- type CookieJar
- type IPSCBurst
- type IPSCClient
- func (c *IPSCClient) Close()
- func (c *IPSCClient) Connect(addr string) error
- func (c *IPSCClient) ConnectWithoutRegistration(addr string) error
- func (c *IPSCClient) Drain(timeout time.Duration) []IPSCBurst
- func (c *IPSCClient) ReceivedPackets() <-chan IPSCBurst
- func (c *IPSCClient) SendGroupVoice(src, dst uint, slot bool, streamID uint32) error
- func (c *IPSCClient) SendPrivateVoice(src, dst uint, slot bool, streamID uint32) error
- func (c *IPSCClient) WaitDisconnected(timeout time.Duration) error
- func (c *IPSCClient) WaitReady(timeout time.Duration) error
- func (c *IPSCClient) WaitReconnected(timeout time.Duration) error
- type IntegrationStack
- func (s *IntegrationStack) AssignTS1StaticTG(t *testing.T, repeaterID, tgID uint)
- func (s *IntegrationStack) AssignTS2StaticTG(t *testing.T, repeaterID, tgID uint)
- func (s *IntegrationStack) SeedEndedNet(t *testing.T, talkgroupID, startedByUserID uint, description string, ...) models.Net
- func (s *IntegrationStack) SeedIPSCRepeater(t *testing.T, id uint, ownerID uint, password string)
- func (s *IntegrationStack) SeedMMDVMRepeater(t *testing.T, id uint, ownerID uint, password string)
- func (s *IntegrationStack) SeedNet(t *testing.T, talkgroupID, startedByUserID uint, description string) models.Net
- func (s *IntegrationStack) SeedPeer(t *testing.T, id uint, ownerID uint, password string, ip string, port int, ...)
- func (s *IntegrationStack) SeedPeerRule(t *testing.T, peerID uint, direction bool, subjectIDMin uint, ...)
- func (s *IntegrationStack) SeedScheduledNet(t *testing.T, talkgroupID, createdByUserID uint, name string, dayOfWeek int, ...) models.ScheduledNet
- func (s *IntegrationStack) SeedTalkgroup(t *testing.T, id uint, name string)
- func (s *IntegrationStack) SeedUser(t *testing.T, id uint, callsign string)
- func (s *IntegrationStack) SpawnSecondReplica(t *testing.T) string
- func (s *IntegrationStack) StartServers(t *testing.T)
- type MMDVMClient
- func (c *MMDVMClient) Close()
- func (c *MMDVMClient) Connect(addr string) error
- func (c *MMDVMClient) Drain(timeout time.Duration) []models.Packet
- func (c *MMDVMClient) ReceivedPackets() <-chan models.Packet
- func (c *MMDVMClient) SendDMRD(pkt models.Packet) error
- func (c *MMDVMClient) WaitReady(timeout time.Duration) error
- type OpenBridgeClient
- func (c *OpenBridgeClient) Close()
- func (c *OpenBridgeClient) Connect(addr string) error
- func (c *OpenBridgeClient) Drain(timeout time.Duration) []models.Packet
- func (c *OpenBridgeClient) LocalAddr() *net.UDPAddr
- func (c *OpenBridgeClient) ReceivedPackets() <-chan models.Packet
- func (c *OpenBridgeClient) SendGroupVoice(src, dst uint, streamID uint32) error
- func (c *OpenBridgeClient) SendRawBytes(data []byte) error
- func (c *OpenBridgeClient) SendRawPacket(pkt models.Packet) error
- type PeerCreateResponse
- type PeerRuleCreateResponse
- type PeerRulesResponse
- type RepeaterCreateResponse
- type TestDB
Constants ¶
This section is empty.
Variables ¶
var ( ErrIPSCHandshakeTimeout = errors.New("IPSC handshake timed out") ErrIPSCDeregisterTimeout = errors.New("timed out waiting for IPSC deregistration") ErrIPSCNotConnected = errors.New("IPSC client not connected") )
var ErrMMDVMHandshakeTimeout = errors.New("MMDVM handshake timed out")
var ErrOpenBridgeNotConnected = errors.New("OpenBridge client not connected")
Functions ¶
func CreateAndLoginUser ¶ added in v1.0.15
func CreateAndLoginUser(t *testing.T, router *gin.Engine, user apimodels.UserRegistration) (APIResponse, *httptest.ResponseRecorder, CookieJar)
func CreateScheduledNet ¶ added in v1.2.36
func CreateScheduledNet(t *testing.T, router *gin.Engine, jar CookieJar, body apimodels.ScheduledNetPost) (apimodels.ScheduledNetResponse, *httptest.ResponseRecorder)
CreateScheduledNet creates a scheduled net via the API.
func DeleteScheduledNet ¶ added in v1.2.36
func DeleteScheduledNet(t *testing.T, router *gin.Engine, jar CookieJar, id uint) *httptest.ResponseRecorder
DeleteScheduledNet deletes a scheduled net via the API.
func ExportNetCheckIns ¶ added in v1.2.36
func ExportNetCheckIns(t *testing.T, router *gin.Engine, jar CookieJar, netID uint, format string) *httptest.ResponseRecorder
ExportNetCheckIns exports check-ins for a net via the API.
func GetNet ¶ added in v1.2.36
func GetNet(t *testing.T, router *gin.Engine, jar CookieJar, netID uint) (apimodels.NetResponse, *httptest.ResponseRecorder)
GetNet retrieves a net by ID via the API.
func GetNetCheckIns ¶ added in v1.2.36
func GetNetCheckIns(t *testing.T, router *gin.Engine, jar CookieJar, netID uint) (*httptest.ResponseRecorder, []byte)
GetNetCheckIns retrieves check-ins for a net via the API.
func GetRepeater ¶ added in v1.2.33
func GetTalkgroup ¶ added in v1.2.33
func ListNets ¶ added in v1.2.36
func ListNets(t *testing.T, router *gin.Engine, jar CookieJar, queryParams string) (*httptest.ResponseRecorder, []byte)
ListNets lists nets via the API.
func LoginAdmin ¶ added in v1.0.15
func LoginAdmin(t *testing.T, router *gin.Engine) (APIResponse, *httptest.ResponseRecorder, CookieJar)
func LoginUser ¶ added in v1.0.15
func LoginUser(t *testing.T, router *gin.Engine, user apimodels.AuthLogin) (APIResponse, *httptest.ResponseRecorder, CookieJar)
func PatchNet ¶ added in v1.2.38
func PatchNet(t *testing.T, router *gin.Engine, jar CookieJar, netID uint, body apimodels.NetPatch) (apimodels.NetResponse, *httptest.ResponseRecorder)
PatchNet updates a net (e.g. showcase toggle) via the API.
func StartNet ¶ added in v1.2.36
func StartNet(t *testing.T, router *gin.Engine, jar CookieJar, body apimodels.NetStartPost) (apimodels.NetResponse, *httptest.ResponseRecorder)
StartNet starts a new net via the API.
Types ¶
type APIResponse ¶
func ApproveUser ¶ added in v1.0.15
func ApproveUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func CreateTalkgroup ¶ added in v1.2.33
func CreateTalkgroup(t *testing.T, router *gin.Engine, jar CookieJar, tg apimodels.TalkgroupPost) (APIResponse, *httptest.ResponseRecorder)
func DeletePeer ¶ added in v1.2.33
func DeletePeer(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func DeletePeerRule ¶ added in v1.2.36
func DeletePeerRule(t *testing.T, router *gin.Engine, peerID uint, ruleID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func DeleteRepeater ¶ added in v1.2.33
func DeleteRepeater(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func DeleteTalkgroup ¶ added in v1.2.33
func DeleteTalkgroup(t *testing.T, router *gin.Engine, id uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func DeleteUser ¶ added in v1.0.15
func DeleteUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func DemoteUser ¶ added in v1.0.15
func DemoteUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func LinkRepeater ¶ added in v1.2.33
func LogoutUser ¶ added in v1.0.15
func LogoutUser(t *testing.T, router *gin.Engine, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func PatchRepeater ¶ added in v1.2.33
func PatchRepeater(t *testing.T, router *gin.Engine, id uint, jar CookieJar, patch apimodels.RepeaterPatch) (APIResponse, *httptest.ResponseRecorder)
func PatchTalkgroup ¶ added in v1.2.33
func PatchTalkgroup(t *testing.T, router *gin.Engine, id uint, jar CookieJar, patch apimodels.TalkgroupPatch) (APIResponse, *httptest.ResponseRecorder)
func PromoteUser ¶ added in v1.0.15
func PromoteUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func RegisterUser ¶ added in v1.0.15
func RegisterUser(t *testing.T, router *gin.Engine, user apimodels.UserRegistration) (APIResponse, *httptest.ResponseRecorder)
func SetRepeaterTalkgroups ¶ added in v1.2.33
func SetRepeaterTalkgroups(t *testing.T, router *gin.Engine, id uint, jar CookieJar, talkgroups apimodels.RepeaterTalkgroupsPost) (APIResponse, *httptest.ResponseRecorder)
func SetTalkgroupAdmins ¶ added in v1.2.33
func SetTalkgroupAdmins(t *testing.T, router *gin.Engine, id uint, jar CookieJar, action apimodels.TalkgroupAdminAction) (APIResponse, *httptest.ResponseRecorder)
func SetTalkgroupNCOs ¶ added in v1.2.33
func SetTalkgroupNCOs(t *testing.T, router *gin.Engine, id uint, jar CookieJar, action apimodels.TalkgroupAdminAction) (APIResponse, *httptest.ResponseRecorder)
func SuspendUser ¶ added in v1.0.15
func SuspendUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
func UnlinkRepeater ¶ added in v1.2.33
func UnsuspendUser ¶ added in v1.0.15
func UnsuspendUser(t *testing.T, router *gin.Engine, dmrID uint, jar CookieJar) (APIResponse, *httptest.ResponseRecorder)
type APIResponseUserList ¶ added in v1.0.15
func ListUsers ¶ added in v1.0.15
func ListUsers(t *testing.T, router *gin.Engine, jar CookieJar) (APIResponseUserList, *httptest.ResponseRecorder)
type Backend ¶ added in v1.2.25
Backend describes a database/cache backend configuration for integration tests.
func PostgresRedisBackend ¶ added in v1.2.25
func PostgresRedisBackend() Backend
PostgresRedisBackend returns a backend that spins up a dedicated Postgres and Redis container for each test. Containers are fully parallel.
func SQLiteMemoryBackend ¶ added in v1.2.25
func SQLiteMemoryBackend() Backend
SQLiteMemoryBackend returns a backend using in-memory SQLite and in-memory pubsub/KV.
type CookieJar ¶ added in v1.0.15
type CookieJar struct {
// contains filtered or unexported fields
}
func (*CookieJar) SetCookies ¶ added in v1.0.15
type IPSCBurst ¶ added in v1.2.25
type IPSCBurst struct {
PacketType byte
PeerID uint32
Src uint
Dst uint
GroupCall bool
Slot bool
Data []byte
}
IPSCBurst represents a raw IPSC user packet received by the simulator client.
type IPSCClient ¶ added in v1.2.25
type IPSCClient struct {
PeerID uint32
AuthKey []byte // raw HMAC-SHA1 key (20 bytes, from decodeAuthKey)
Password string // hex auth key string
// contains filtered or unexported fields
}
IPSCClient is a simulated IPSC peer client for integration testing. It performs the full IPSC registration handshake (MasterRegisterRequest → MasterRegisterReply) and can send/receive IPSC voice burst packets over UDP.
func NewIPSCClient ¶ added in v1.2.25
func NewIPSCClient(peerID uint32, password string) *IPSCClient
NewIPSCClient creates a new IPSC simulator client. password is the hex auth key string as stored in the database.
func (*IPSCClient) Close ¶ added in v1.2.25
func (c *IPSCClient) Close()
Close shuts down the client.
func (*IPSCClient) Connect ¶ added in v1.2.25
func (c *IPSCClient) Connect(addr string) error
Connect dials the IPSC server and starts the registration handshake.
func (*IPSCClient) ConnectWithoutRegistration ¶ added in v1.2.29
func (c *IPSCClient) ConnectWithoutRegistration(addr string) error
ConnectWithoutRegistration dials the IPSC server but does NOT send a MasterRegisterRequest. The client can still send HMAC-signed packets (e.g. voice data) through the UDP socket. This is useful for testing that the server rejects traffic from peers that have not completed the registration handshake.
func (*IPSCClient) Drain ¶ added in v1.2.25
func (c *IPSCClient) Drain(timeout time.Duration) []IPSCBurst
Drain collects all packets received within the given timeout window.
func (*IPSCClient) ReceivedPackets ¶ added in v1.2.25
func (c *IPSCClient) ReceivedPackets() <-chan IPSCBurst
ReceivedPackets returns a channel of IPSC bursts received from the server.
func (*IPSCClient) SendGroupVoice ¶ added in v1.2.25
func (c *IPSCClient) SendGroupVoice(src, dst uint, slot bool, streamID uint32) error
SendGroupVoice sends an IPSC group voice burst with a voice LC header, a voice burst, and a terminator.
func (*IPSCClient) SendPrivateVoice ¶ added in v1.2.25
func (c *IPSCClient) SendPrivateVoice(src, dst uint, slot bool, streamID uint32) error
SendPrivateVoice sends an IPSC private voice burst.
func (*IPSCClient) WaitDisconnected ¶ added in v1.2.29
func (c *IPSCClient) WaitDisconnected(timeout time.Duration) error
WaitDisconnected blocks until the client receives a DeregistrationRequest from the server.
func (*IPSCClient) WaitReady ¶ added in v1.2.25
func (c *IPSCClient) WaitReady(timeout time.Duration) error
WaitReady blocks until the registration handshake is complete.
func (*IPSCClient) WaitReconnected ¶ added in v1.2.29
func (c *IPSCClient) WaitReconnected(timeout time.Duration) error
WaitReconnected blocks until the client has completed a re-handshake after a deregistration disconnect. Returns ErrIPSCHandshakeTimeout if the re-handshake does not complete within the timeout.
type IntegrationStack ¶ added in v1.2.25
type IntegrationStack struct {
Config *config.Config
DB *gorm.DB
Hub *hub.Hub
PubSub pubsub.PubSub
KV kv.KV
CallTracker *calltracker.CallTracker
MMDVMServer *mmdvm.Server
IPSCServer *ipsc.IPSCServer
OpenBridgeServer *openbridge.Server
MMDVMAddr string // host:port of the MMDVM server
IPSCAddr string // host:port of the IPSC server
OpenBridgeAddr string // host:port of the OpenBridge server
}
IntegrationStack is a full DMRHub test environment with real MMDVM and IPSC servers on ephemeral UDP ports, backed by in-memory SQLite, pubsub, and KV.
func SetupIntegrationStack ¶ added in v1.2.25
func SetupIntegrationStack(t *testing.T, backends ...Backend) *IntegrationStack
SetupIntegrationStack creates and starts a full integration test environment. The hub is NOT started yet — call SeedAndStart() after seeding your DB data.
func (*IntegrationStack) AssignTS1StaticTG ¶ added in v1.2.25
func (s *IntegrationStack) AssignTS1StaticTG(t *testing.T, repeaterID, tgID uint)
AssignTS1StaticTG adds a talkgroup to a repeater's TS1 static list.
func (*IntegrationStack) AssignTS2StaticTG ¶ added in v1.2.25
func (s *IntegrationStack) AssignTS2StaticTG(t *testing.T, repeaterID, tgID uint)
AssignTS2StaticTG adds a talkgroup to a repeater's TS2 static list.
func (*IntegrationStack) SeedEndedNet ¶ added in v1.2.36
func (s *IntegrationStack) SeedEndedNet(t *testing.T, talkgroupID, startedByUserID uint, description string, duration time.Duration) models.Net
SeedEndedNet creates an ended net in the database for integration testing.
func (*IntegrationStack) SeedIPSCRepeater ¶ added in v1.2.25
SeedIPSCRepeater creates an IPSC repeater in the DB.
func (*IntegrationStack) SeedMMDVMRepeater ¶ added in v1.2.25
SeedMMDVMRepeater creates an MMDVM repeater in the DB.
func (*IntegrationStack) SeedNet ¶ added in v1.2.36
func (s *IntegrationStack) SeedNet(t *testing.T, talkgroupID, startedByUserID uint, description string) models.Net
SeedNet creates an active net in the database for integration testing.
func (*IntegrationStack) SeedPeer ¶ added in v1.2.36
func (s *IntegrationStack) SeedPeer(t *testing.T, id uint, ownerID uint, password string, ip string, port int, ingress bool, egress bool)
SeedPeer creates an OpenBridge peer in the DB.
func (*IntegrationStack) SeedPeerRule ¶ added in v1.2.36
func (s *IntegrationStack) SeedPeerRule(t *testing.T, peerID uint, direction bool, subjectIDMin uint, subjectIDMax uint)
SeedPeerRule creates a peer rule in the DB.
func (*IntegrationStack) SeedScheduledNet ¶ added in v1.2.36
func (s *IntegrationStack) SeedScheduledNet(t *testing.T, talkgroupID, createdByUserID uint, name string, dayOfWeek int, timeOfDay, timezone string) models.ScheduledNet
SeedScheduledNet creates a scheduled net in the database for integration testing.
func (*IntegrationStack) SeedTalkgroup ¶ added in v1.2.25
func (s *IntegrationStack) SeedTalkgroup(t *testing.T, id uint, name string)
SeedTalkgroup creates a Talkgroup in the DB.
func (*IntegrationStack) SeedUser ¶ added in v1.2.25
func (s *IntegrationStack) SeedUser(t *testing.T, id uint, callsign string)
SeedUser creates a User in the DB.
func (*IntegrationStack) SpawnSecondReplica ¶ added in v1.2.26
func (s *IntegrationStack) SpawnSecondReplica(t *testing.T) string
SpawnSecondReplica creates a second Hub + MMDVM server that shares the same DB, pubsub, and KV as the original stack — simulating two replicas of the app. The second replica's Hub is started; repeater subscriptions are activated when repeaters connect via the MMDVM handshake. Returns the second MMDVM server's listen address.
func (*IntegrationStack) StartServers ¶ added in v1.2.25
func (s *IntegrationStack) StartServers(t *testing.T)
StartServers starts the Hub and the MMDVM, IPSC, and OpenBridge servers. Repeater subscriptions are activated lazily when repeaters connect via the protocol handshake.
type MMDVMClient ¶ added in v1.2.25
type MMDVMClient struct {
RepeaterID uint32
Callsign string
Password string
// contains filtered or unexported fields
}
MMDVMClient is a simulated MMDVM repeater client for integration testing. It performs the full Homebrew protocol handshake (RPTL → RPTACK → RPTK → RPTACK → RPTC → RPTACK) and can send/receive DMRD voice packets over UDP.
func NewMMDVMClient ¶ added in v1.2.25
func NewMMDVMClient(repeaterID uint32, callsign, password string) *MMDVMClient
NewMMDVMClient creates a new MMDVM simulator client.
func (*MMDVMClient) Close ¶ added in v1.2.25
func (c *MMDVMClient) Close()
Close shuts down the client.
func (*MMDVMClient) Connect ¶ added in v1.2.25
func (c *MMDVMClient) Connect(addr string) error
Connect dials the MMDVM server and starts the handshake.
func (*MMDVMClient) Drain ¶ added in v1.2.25
func (c *MMDVMClient) Drain(timeout time.Duration) []models.Packet
Drain collects all packets received within the given timeout window. Useful for negative assertions (proving nothing extra was delivered).
func (*MMDVMClient) ReceivedPackets ¶ added in v1.2.25
func (c *MMDVMClient) ReceivedPackets() <-chan models.Packet
ReceivedPackets returns a channel of DMRD packets received from the server.
type OpenBridgeClient ¶ added in v1.2.36
type OpenBridgeClient struct {
PeerID uint32
Password string
// contains filtered or unexported fields
}
OpenBridgeClient is a simulated OpenBridge peer client for integration testing. OpenBridge is stateless (no handshake) — packets are authenticated via HMAC-SHA1.
func NewOpenBridgeClient ¶ added in v1.2.36
func NewOpenBridgeClient(peerID uint32, password string) *OpenBridgeClient
NewOpenBridgeClient creates a new OpenBridge simulator client.
func (*OpenBridgeClient) Close ¶ added in v1.2.36
func (c *OpenBridgeClient) Close()
Close shuts down the client.
func (*OpenBridgeClient) Connect ¶ added in v1.2.36
func (c *OpenBridgeClient) Connect(addr string) error
Connect dials the OpenBridge server. No handshake is needed.
func (*OpenBridgeClient) Drain ¶ added in v1.2.36
func (c *OpenBridgeClient) Drain(timeout time.Duration) []models.Packet
Drain collects all packets received within the given timeout window.
func (*OpenBridgeClient) LocalAddr ¶ added in v1.2.36
func (c *OpenBridgeClient) LocalAddr() *net.UDPAddr
LocalAddr returns the local UDP address of the client. Useful for configuring the peer's IP/Port in the DB for outbound delivery.
func (*OpenBridgeClient) ReceivedPackets ¶ added in v1.2.36
func (c *OpenBridgeClient) ReceivedPackets() <-chan models.Packet
ReceivedPackets returns a channel of packets received from the server.
func (*OpenBridgeClient) SendGroupVoice ¶ added in v1.2.36
func (c *OpenBridgeClient) SendGroupVoice(src, dst uint, streamID uint32) error
SendGroupVoice sends an OpenBridge group voice packet (voice head + voice + terminator).
func (*OpenBridgeClient) SendRawBytes ¶ added in v1.2.36
func (c *OpenBridgeClient) SendRawBytes(data []byte) error
SendRawBytes sends raw bytes over the UDP connection (no HMAC added). Useful for testing invalid HMAC scenarios.
func (*OpenBridgeClient) SendRawPacket ¶ added in v1.2.36
func (c *OpenBridgeClient) SendRawPacket(pkt models.Packet) error
SendRawPacket sends a single DMRD packet with HMAC appended.
type PeerCreateResponse ¶ added in v1.2.33
type PeerCreateResponse struct {
Message string `json:"message"`
Password string `json:"password"`
Error string `json:"error"`
}
func CreatePeer ¶ added in v1.2.33
func CreatePeer(t *testing.T, router *gin.Engine, jar CookieJar, peer apimodels.PeerPost) (PeerCreateResponse, *httptest.ResponseRecorder)
type PeerRuleCreateResponse ¶ added in v1.2.36
type PeerRuleCreateResponse struct {
Message string `json:"message"`
Rule models.PeerRule `json:"rule"`
Error string `json:"error"`
}
func CreatePeerRule ¶ added in v1.2.36
func CreatePeerRule(t *testing.T, router *gin.Engine, peerID uint, jar CookieJar, rule apimodels.PeerRulePost) (PeerRuleCreateResponse, *httptest.ResponseRecorder)
type PeerRulesResponse ¶ added in v1.2.36
type PeerRulesResponse struct {
Rules []models.PeerRule `json:"rules"`
Error string `json:"error"`
}
func GetPeerRules ¶ added in v1.2.36
func GetPeerRules(t *testing.T, router *gin.Engine, peerID uint, jar CookieJar) (PeerRulesResponse, *httptest.ResponseRecorder)
type RepeaterCreateResponse ¶ added in v1.2.33
type RepeaterCreateResponse struct {
Message string `json:"message"`
Password string `json:"password"`
Error string `json:"error"`
}
func CreateRepeater ¶ added in v1.2.33
func CreateRepeater(t *testing.T, router *gin.Engine, jar CookieJar, repeater apimodels.RepeaterPost) (RepeaterCreateResponse, *httptest.ResponseRecorder)
type TestDB ¶
type TestDB struct {
// contains filtered or unexported fields
}