Skip to content

Commit

Permalink
fix(server): use UTC and portable path composition (#44)
Browse files Browse the repository at this point in the history
This diff implements portable path composition theoretically allowing
the server to run under Windows systems.

Additionally, this diff implements tests to ensure that we're still
composing the output file path correctly.

While there, notice we're not using UTC and enforce UTC.
bassosimone authored Jan 30, 2024
1 parent cd6674a commit 2c6d5ad
Showing 2 changed files with 23 additions and 13 deletions.
16 changes: 10 additions & 6 deletions server/server.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import (
"net/http"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"sync"
@@ -34,6 +35,11 @@ type sessionInfo struct {
stamp time.Time
}

// timeNowUTC returns the current time using UTC.
func timeNowUTC() time.Time {
return time.Now().UTC()
}

// dependencies abstracts the dependencies used by [*Handler].
type dependencies struct {
GzipNewWriterLevel func(w io.Writer, level int) (*gzip.Writer, error)
@@ -104,7 +110,7 @@ func NewHandler(datadir string, logger model.Logger) *Handler {
//
// This method LOCKS and MUTATES the .sessions field.
func (h *Handler) createSession(UUID string) {
now := time.Now()
now := timeNowUTC()
session := &sessionInfo{
stamp: now,
serverSchema: model.ServerSchema{
@@ -156,7 +162,7 @@ func (h *Handler) getSessionState(UUID string) sessionState {
// The integer argument, currently ignored, contains the number of bytes
// that were sent as part of the current DASH iteration.
func (h *Handler) updateSession(UUID string, _ int) {
now := time.Now()
now := timeNowUTC()
h.mtx.Lock()
defer h.mtx.Unlock()
session, ok := h.sessions[UUID]
@@ -198,7 +204,7 @@ func (h *Handler) reapStaleSessions() {
h.mtx.Lock()
defer h.mtx.Unlock()
h.logger.Debugf("reapStaleSessions: inspecting %d sessions", len(h.sessions))
now := time.Now()
now := timeNowUTC()
var stale []string
for UUID, session := range h.sessions {
const toomuch = 60 * time.Second
@@ -381,9 +387,7 @@ func (h *Handler) savedata(session *sessionInfo) error {
}

// append the file name to the path
//
// TODO(bassosimone): this code does not work as intended on Windows
name += "/neubot-dash-" + session.stamp.Format("20060102T150405.000000000Z") + ".json.gz"
name = filepath.Join(name, "neubot-dash-"+session.stamp.Format("20060102T150405.000000000Z")+".json.gz")

// open the results file
//
20 changes: 13 additions & 7 deletions server/server_test.go
Original file line number Diff line number Diff line change
@@ -7,7 +7,6 @@ import (
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
@@ -72,7 +71,7 @@ func TestServerNegotiate(t *testing.T) {
if resp.StatusCode != 200 {
t.Fatal("Expected different status code")
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
@@ -213,7 +212,7 @@ func TestServerDownload(t *testing.T) {
if resp.StatusCode != 200 {
t.Fatal("Expected different status code")
}
data, err := ioutil.ReadAll(resp.Body)
data, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
@@ -268,7 +267,7 @@ func TestServerSaveData(t *testing.T) {
handler.deps.OSOpenFile = func(
name string, flag int, perm os.FileMode,
) (*os.File, error) {
return ioutil.TempFile("", "neubot-dash-tests")
return os.CreateTemp("", "neubot-dash-tests")
}
handler.deps.GzipNewWriterLevel = func(
w io.Writer, level int,
@@ -292,7 +291,7 @@ func TestServerSaveData(t *testing.T) {
handler.deps.OSOpenFile = func(
name string, flag int, perm os.FileMode,
) (*os.File, error) {
return ioutil.TempFile("", "neubot-dash-tests")
return os.CreateTemp("", "neubot-dash-tests")
}
handler.deps.JSONMarshal = func(v interface{}) ([]byte, error) {
return nil, errors.New("Mocked error")
@@ -311,15 +310,22 @@ func TestServerSaveData(t *testing.T) {
handler.deps.OSMkdirAll = func(path string, perm os.FileMode) error {
return nil
}
sessionInfo.stamp = time.Date(2024, time.January, 29, 20, 23, 0, 0, time.UTC) // predictable
expectFilename := "dash/2024/01/29/neubot-dash-20240129T202300.000000000Z.json.gz"
var gotFilename string
handler.deps.OSOpenFile = func(
name string, flag int, perm os.FileMode,
) (*os.File, error) {
return ioutil.TempFile("", "neubot-dash-tests")
gotFilename = name
return os.CreateTemp("", "neubot-dash-tests")
}
err := handler.savedata(sessionInfo)
if err != nil {
t.Fatal(err)
}
if gotFilename != expectFilename {
t.Fatal("expected", expectFilename, "got", gotFilename)
}
})
}

@@ -335,7 +341,7 @@ func TestServerCollect(t *testing.T) {
}
})

t.Run("ioutil.ReadAll failure", func(t *testing.T) {
t.Run("io.ReadAll failure", func(t *testing.T) {
const session = "deadbeef"
handler := NewHandler("", log.Log)
handler.createSession(session)

0 comments on commit 2c6d5ad

Please sign in to comment.