improve docs and tests

This commit is contained in:
Martin/Geno 2018-08-23 21:02:51 +02:00
parent 5fd5733261
commit d5533157a3
No known key found for this signature in database
GPG Key ID: 9D7D3C6BFF600C6A
14 changed files with 135 additions and 53 deletions

View File

@ -1,8 +1,9 @@
// Package that provides the functionality to open, close and use a database // Package database provides the functionality to open, close and use a database
package database package database
import ( import (
"github.com/jinzhu/gorm" "github.com/jinzhu/gorm"
// load gorm defaults dialects
_ "github.com/jinzhu/gorm/dialects/mysql" _ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/postgres" _ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/sqlite" _ "github.com/jinzhu/gorm/dialects/sqlite"
@ -10,10 +11,10 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
// Database connection for writing purposes // Write Database connection for writing purposes
var Write *gorm.DB var Write *gorm.DB
// Database connection for reading purposes // Read Database connection for reading purposes
var Read *gorm.DB var Read *gorm.DB
// Configuration files // Configuration files
@ -22,7 +23,7 @@ var (
runtime []interface{} runtime []interface{}
) )
// Configuration of the database connection // Config of the database connection
type Config struct { type Config struct {
// type of the database, currently supports sqlite and postgres // type of the database, currently supports sqlite and postgres
Type string Type string
@ -34,7 +35,7 @@ type Config struct {
Logging bool Logging bool
} }
// Function to open a database and set the given configuration // Open database and set the given configuration
func Open(c Config) (err error) { func Open(c Config) (err error) {
writeLog := log.WithField("db", "write") writeLog := log.WithField("db", "write")
config = &c config = &c
@ -65,7 +66,7 @@ func Open(c Config) (err error) {
return return
} }
// Function to safely close the database // Close connnection to database safely
func Close() { func Close() {
Write.Close() Write.Close()
if len(config.ReadConnection) > 0 { if len(config.ReadConnection) > 0 {
@ -73,7 +74,7 @@ func Close() {
} }
} }
// Function to add a model to the runtime // AddModel to the runtime
func AddModel(m interface{}) { func AddModel(m interface{}) {
runtime = append(runtime, m) runtime = append(runtime, m)
} }

View File

@ -8,18 +8,14 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
) )
// ReadConfigFile reads a config model from path of a yml file // ReadTOML reads a config model from path of a yml file
func ReadTOML(path string, data interface{}) error { func ReadTOML(path string, data interface{}) error {
file, err := ioutil.ReadFile(path) file, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return err return err
} }
if err := toml.Unmarshal(file, data); err != nil { return toml.Unmarshal(file, data)
return err
}
return nil
} }
// ReadJSON reads a config model from path of a yml file // ReadJSON reads a config model from path of a yml file
@ -29,11 +25,7 @@ func ReadJSON(path string, data interface{}) error {
return err return err
} }
if err := json.NewDecoder(file).Decode(data); err != nil { return json.NewDecoder(file).Decode(data)
return err
}
return nil
} }
// SaveJSON to path // SaveJSON to path
@ -45,13 +37,11 @@ func SaveJSON(outputFile string, data interface{}) error {
return err return err
} }
if err := json.NewEncoder(file).Encode(data); err != nil { err = json.NewEncoder(file).Encode(data)
if err != nil {
return err return err
} }
file.Close() file.Close()
if err := os.Rename(tmpFile, outputFile); err != nil { return os.Rename(tmpFile, outputFile)
return err
}
return nil
} }

65
file/main_test.go Normal file
View File

@ -0,0 +1,65 @@
package file
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestReadTOML(t *testing.T) {
assert := assert.New(t)
a := struct {
Text string `toml:"text"`
}{}
err := ReadTOML("testfiles/donoexists", &a)
assert.Error(err, "could find file ^^")
err = ReadTOML("testfiles/trash.txt", &a)
assert.Error(err, "could marshel file ^^")
err = ReadTOML("testfiles/ok.toml", &a)
assert.NoError(err)
assert.Equal("hallo", a.Text)
}
func TestReadJSON(t *testing.T) {
assert := assert.New(t)
a := struct {
Text string `toml:"text"`
}{}
err := ReadJSON("testfiles/donoexists", &a)
assert.Error(err, "could find file ^^")
err = ReadJSON("testfiles/trash.txt", &a)
assert.Error(err, "could marshel file ^^")
err = ReadJSON("testfiles/ok.json", &a)
assert.NoError(err)
assert.Equal("hallo", a.Text)
}
func TestSaveJSON(t *testing.T) {
assert := assert.New(t)
tmpfile, _ := ioutil.TempFile("/tmp", "lib-json-testfile.json")
err := SaveJSON(tmpfile.Name(), 3)
assert.NoError(err, "could not save temp")
err = SaveJSON(tmpfile.Name(), tmpfile.Name)
assert.Error(err, "could not save func")
err = SaveJSON("/dev/null", 4)
assert.Error(err, "could not save to /dev/null")
var testvalue int
err = ReadJSON(tmpfile.Name(), &testvalue)
assert.NoError(err)
assert.Equal(3, testvalue)
os.Remove(tmpfile.Name())
}

3
file/testfiles/ok.json Normal file
View File

@ -0,0 +1,3 @@
{
"text": "hallo"
}

1
file/testfiles/ok.toml Normal file
View File

@ -0,0 +1 @@
text = "hallo"

1
file/testfiles/trash.txt Normal file
View File

@ -0,0 +1 @@
wrong format example

View File

@ -6,6 +6,7 @@ import (
"dev.sum7.eu/genofire/golang-lib/worker" "dev.sum7.eu/genofire/golang-lib/worker"
) )
// NewSaveJSONWorker Starts a worker, which save periodly data to json file
func NewSaveJSONWorker(repeat time.Duration, path string, data interface{}) *worker.Worker { func NewSaveJSONWorker(repeat time.Duration, path string, data interface{}) *worker.Worker {
saveWorker := worker.NewWorker(repeat, func() { saveWorker := worker.NewWorker(repeat, func() {
SaveJSON(path, data) SaveJSON(path, data)

27
file/worker_test.go Normal file
View File

@ -0,0 +1,27 @@
package file
import (
"io/ioutil"
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestSaveJSONWorker(t *testing.T) {
assert := assert.New(t)
tmpfile, _ := ioutil.TempFile("/tmp", "lib-json-workertest.json")
worker := NewSaveJSONWorker(100*time.Millisecond, tmpfile.Name(), 12)
assert.NotNil(worker)
time.Sleep(300 * time.Millisecond)
var testvalue int
err := ReadJSON(tmpfile.Name(), &testvalue)
assert.NoError(err)
assert.Equal(12, testvalue)
os.Remove(tmpfile.Name())
}

View File

@ -1,4 +1,4 @@
// Package that provides the logic of the webserver // Package http provides the logic of the webserver
package http package http
import ( import (
@ -8,7 +8,7 @@ import (
"strings" "strings"
) )
// Function to read data from a http request via json format (input) // Read data from a http request via json format (input)
func Read(r *http.Request, to interface{}) (err error) { func Read(r *http.Request, to interface{}) (err error) {
if !strings.Contains(r.Header.Get("Content-Type"), "application/json") { if !strings.Contains(r.Header.Get("Content-Type"), "application/json") {
err = errors.New("no json request received") err = errors.New("no json request received")
@ -18,7 +18,7 @@ func Read(r *http.Request, to interface{}) (err error) {
return return
} }
// Function to write data as json to a http response (output) // Write data as json to a http response (output)
func Write(w http.ResponseWriter, data interface{}) { func Write(w http.ResponseWriter, data interface{}) {
js, err := json.Marshal(data) js, err := json.Marshal(data)
if err != nil { if err != nil {

View File

@ -2,6 +2,7 @@ package http
import "net/http" import "net/http"
// GetRemoteIP of http Request
func GetRemoteIP(r *http.Request) string { func GetRemoteIP(r *http.Request) string {
ip := r.Header.Get("X-Forwarded-For") ip := r.Header.Get("X-Forwarded-For")
if len(ip) <= 1 { if len(ip) <= 1 {

View File

@ -7,8 +7,9 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
const channelBufSize = 100 const channelBufSize = 1000
// Client of Websocket Server Connection
type Client struct { type Client struct {
id uuid.UUID id uuid.UUID
server *Server server *Server
@ -18,12 +19,6 @@ type Client struct {
readQuit chan bool readQuit chan bool
} }
func NewTestClient(out chan *Message) *Client {
return &Client{
out: out,
}
}
func NewClient(s *Server, ws *websocket.Conn) *Client { func NewClient(s *Server, ws *websocket.Conn) *Client {
if ws == nil { if ws == nil {

View File

@ -66,7 +66,6 @@ func (s *Server) DelClient(c *Client) {
} }
} }
} }
func (s *Server) SendAll(msg *Message) { func (s *Server) SendAll(msg *Message) {
s.clientsMutex.Lock() s.clientsMutex.Lock()
defer s.clientsMutex.Unlock() defer s.clientsMutex.Unlock()

View File

@ -3,10 +3,10 @@ package websocket
import ( import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"sync"
"testing" "testing"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -39,14 +39,14 @@ func TestServerSendAll(t *testing.T) {
srv := NewServer(nil, nil) srv := NewServer(nil, nil)
assert.NotNil(srv) assert.NotNil(srv)
out1 := make(chan *Message) out1 := make(chan *Message, 2)
c1 := &Client{ c1 := &Client{
id: uuid.New(), id: uuid.New(),
out: out1, out: out1,
server: srv, server: srv,
} }
out2 := make(chan *Message) out2 := make(chan *Message, 2)
c2 := &Client{ c2 := &Client{
id: uuid.New(), id: uuid.New(),
out: out2, out: out2,
@ -55,22 +55,21 @@ func TestServerSendAll(t *testing.T) {
srv.AddClient(c1) srv.AddClient(c1)
srv.AddClient(c2) srv.AddClient(c2)
go func() { wg := sync.WaitGroup{}
msg := <-out1 client := func(out chan *Message) {
msg := <-out
assert.Equal("hi", msg.Subject) assert.Equal("hi", msg.Subject)
wg.Done()
}() }
go func() { wg.Add(2)
go client(out1)
msg := <-out2 go client(out2)
assert.Equal("hi", msg.Subject)
}()
srv.SendAll(&Message{ srv.SendAll(&Message{
Subject: "hi", Subject: "hi",
}) })
wg.Wait()
srv.DelClient(c2) srv.DelClient(c2)
srv.DelClient(c1) srv.DelClient(c1)

View File

@ -1,4 +1,4 @@
// Package with a lib for cronjobs to run in background // Package worker a lib for cronjobs to run in background
package worker package worker
import ( import (
@ -6,7 +6,7 @@ import (
"time" "time"
) )
// Struct which handles the job // Worker Struct which handles the job
type Worker struct { type Worker struct {
every time.Duration every time.Duration
run func() run func()
@ -14,7 +14,7 @@ type Worker struct {
wg sync.WaitGroup wg sync.WaitGroup
} }
// Function to create a new Worker with a timestamp, run, every and it's function // NewWorker create a Worker with a timestamp, run, every and it's function
func NewWorker(every time.Duration, f func()) (w *Worker) { func NewWorker(every time.Duration, f func()) (w *Worker) {
w = &Worker{ w = &Worker{
every: every, every: every,
@ -24,8 +24,7 @@ func NewWorker(every time.Duration, f func()) (w *Worker) {
return return
} }
// Function to start the Worker // Start the Worker
// (please us it as a go routine with go w.Start())
func (w *Worker) Start() { func (w *Worker) Start() {
w.wg.Add(1) w.wg.Add(1)
go func() { go func() {
@ -43,7 +42,7 @@ func (w *Worker) Start() {
}() }()
} }
// Function to stop the Worker // Close stops the Worker
func (w *Worker) Close() { func (w *Worker) Close() {
close(w.quit) close(w.quit)
w.wg.Wait() w.wg.Wait()