Skip to content

Commit

Permalink
Add missing tests for cmd/offline
Browse files Browse the repository at this point in the history
  • Loading branch information
gandarez committed Nov 9, 2024
1 parent 8aa3a64 commit 265065a
Show file tree
Hide file tree
Showing 7 changed files with 317 additions and 3 deletions.
12 changes: 9 additions & 3 deletions cmd/heartbeat/heartbeat_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ func TestSendHeartbeats(t *testing.T) {
tmpFile, err := os.CreateTemp(t.TempDir(), "wakatime-config")
require.NoError(t, err)

defer tmpFile.Close()

subfolders := project.CountSlashesInProjectFolder(projectFolder)

router.HandleFunc("/users/current/heartbeats.bulk", func(w http.ResponseWriter, req *http.Request) {
Expand Down Expand Up @@ -544,12 +546,12 @@ func TestSendHeartbeats_NonExistingEntity(t *testing.T) {

ctx = log.ToContext(ctx, logger)

f, err := os.CreateTemp(tmpDir, "")
offlineQueueFile, err := os.CreateTemp(tmpDir, "")
require.NoError(t, err)

defer f.Close()
defer offlineQueueFile.Close()

err = cmdheartbeat.SendHeartbeats(ctx, v, f.Name())
err = cmdheartbeat.SendHeartbeats(ctx, v, offlineQueueFile.Name())
require.NoError(t, err)

output, err := io.ReadAll(logFile)
Expand Down Expand Up @@ -1061,6 +1063,8 @@ func TestSendHeartbeats_ObfuscateProject(t *testing.T) {
offlineQueueFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer offlineQueueFile.Close()

err = cmdheartbeat.SendHeartbeats(ctx, v, offlineQueueFile.Name())
require.NoError(t, err)

Expand Down Expand Up @@ -1150,6 +1154,8 @@ func TestSendHeartbeats_ObfuscateProjectNotBranch(t *testing.T) {
offlineQueueFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer offlineQueueFile.Close()

err = cmdheartbeat.SendHeartbeats(ctx, v, offlineQueueFile.Name())
require.NoError(t, err)

Expand Down
113 changes: 113 additions & 0 deletions cmd/offline/offline_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package offline_test

import (
"context"
"encoding/json"
"os"
"testing"

cmdoffline "github.com/wakatime/wakatime-cli/cmd/offline"
"github.com/wakatime/wakatime-cli/pkg/heartbeat"
"github.com/wakatime/wakatime-cli/pkg/offline"

"github.com/spf13/viper"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestSaveHeartbeats(t *testing.T) {
tmpFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer tmpFile.Close()

offlineQueueFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer offlineQueueFile.Close()

ctx := context.Background()

v := viper.New()
v.Set("config", tmpFile.Name())
v.Set("category", "debugging")
v.Set("cursorpos", 42)
v.Set("entity", "testdata/main.go")
v.Set("entity-type", "file")
v.Set("key", "00000000-0000-4000-8000-000000000000")
v.Set("language", "Go")
v.Set("alternate-language", "Golang")
v.Set("hide-branch-names", true)
v.Set("project", "wakatime-cli")
v.Set("lineno", 13)
v.Set("time", 1585598059.1)
v.Set("timeout", 5)
v.Set("write", true)

err = cmdoffline.SaveHeartbeats(ctx, v, nil, offlineQueueFile.Name())
require.NoError(t, err)

offlineCount, err := offline.CountHeartbeats(ctx, offlineQueueFile.Name())
require.NoError(t, err)

assert.Equal(t, 1, offlineCount)
}

func TestSaveHeartbeats_ExtraHeartbeats(t *testing.T) {
tmpFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer tmpFile.Close()

offlineQueueFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer offlineQueueFile.Close()

ctx := context.Background()

data, err := os.ReadFile("testdata/extra_heartbeats.json")
require.NoError(t, err)

var hh []heartbeat.Heartbeat

err = json.Unmarshal(data, &hh)
require.NoError(t, err)

v := viper.New()
v.Set("config", tmpFile.Name())
v.Set("entity", "testdata/main.go")
v.Set("key", "00000000-0000-4000-8000-000000000000")

err = cmdoffline.SaveHeartbeats(ctx, v, hh, offlineQueueFile.Name())
require.NoError(t, err)

offlineCount, err := offline.CountHeartbeats(ctx, offlineQueueFile.Name())
require.NoError(t, err)

assert.Equal(t, 25, offlineCount)
}

func TestSaveHeartbeats_OfflineDisabled(t *testing.T) {
tmpFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer tmpFile.Close()

offlineQueueFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer offlineQueueFile.Close()

ctx := context.Background()

v := viper.New()
v.Set("config", tmpFile.Name())
v.Set("disable-offline", true)
v.Set("entity", "testdata/main.go")
v.Set("key", "00000000-0000-4000-8000-000000000000")

err = cmdoffline.SaveHeartbeats(ctx, v, nil, offlineQueueFile.Name())

assert.EqualError(t, err, "saving to offline db disabled")
}
1 change: 1 addition & 0 deletions cmd/offline/testdata/extra_heartbeats.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[ { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598059 }, { "alternate_language": "Py", "category": "debugging", "cursorpos": null, "entity": "testdata/main.py", "is_write": null, "language": "Python", "lineno": null, "lines": null, "project": "wakatime-cli", "type": "file", "timestamp": 1585598060 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598061 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598062 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598063 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598064 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598065 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598066 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598067 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598068 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598069 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598070 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598071 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598072 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598073 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598074 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598075 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598076 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598077 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598078 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598079 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598080 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598081 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598082 }, { "alternate_language": "Golang", "alternate_project": "billing", "category": "coding", "cursorpos": 12, "entity": "testdata/main.go", "entity_type": "file", "is_write": true, "language": "Go", "lineno": 42, "lines": 45, "project": "wakatime-cli", "time": 1585598083 } ]
3 changes: 3 additions & 0 deletions cmd/offline/testdata/localfile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hello
hello
world
11 changes: 11 additions & 0 deletions cmd/offline/testdata/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

import (
"fmt"
"os"
)

func main() {
fmt.Println("hello world")
os.Exit(0)
}
20 changes: 20 additions & 0 deletions cmd/offline/testdata/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# vim: set filetype=python

from __future__ import print_statement

import os, sys
from flask import session, render_template
import simplejson as json


class MyClass(object):
"""this class
"""

def method1(self):
a = 1 + 2
b = 'hello world!'
for x in y:
print(x)
raise Exception()
160 changes: 160 additions & 0 deletions cmd/run_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,166 @@ func TestRunCmd_Err(t *testing.T) {
assert.Equal(t, exitcode.ErrGeneric, err.(exitcode.Err).Code)
}

func TestRunCmd_Panic(t *testing.T) {
testServerURL, router, tearDown := setupTestServer()
defer tearDown()

version.OS = "some os"
version.Arch = "some architecture"
version.Version = "some version"

router.HandleFunc("/plugins/errors", func(w http.ResponseWriter, req *http.Request) {
// check request
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, []string{"Basic MDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAw"}, req.Header["Authorization"])
assert.Equal(t, []string{"application/json"}, req.Header["Content-Type"])

expectedBodyTpl, err := os.ReadFile("testdata/diagnostics_request_template.json")
require.NoError(t, err)

body, err := io.ReadAll(req.Body)
require.NoError(t, err)

var diagnostics struct {
Architecture string `json:"architecture"`
CliVersion string `json:"cli_version"`
Editor string `json:"editor"`
Logs string `json:"logs"`
OriginalError string `json:"error_message"`
Platform string `json:"platform"`
Plugin string `json:"plugin"`
Stack string `json:"stacktrace"`
}

err = json.Unmarshal(body, &diagnostics)
require.NoError(t, err)

expectedBodyStr := fmt.Sprintf(
string(expectedBodyTpl),
jsonEscape(t, diagnostics.OriginalError),
jsonEscape(t, diagnostics.Logs),
jsonEscape(t, diagnostics.Stack),
)

assert.JSONEq(t, expectedBodyStr, string(body))

// send response
w.WriteHeader(http.StatusCreated)
})

logFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer logFile.Close()

ctx := context.Background()

v := viper.New()
v.Set("api-url", testServerURL)
v.Set("log-file", logFile.Name())

logger, err := SetupLogging(ctx, v)
require.NoError(t, err)

defer logger.Flush()

ctx = log.ToContext(ctx, logger)

err = runCmd(ctx, v, false, false, func(_ context.Context, _ *viper.Viper) (int, error) {
panic("fail")
})

var errexitcode exitcode.Err

require.ErrorAs(t, err, &errexitcode)
assert.Equal(t, exitcode.ErrGeneric, err.(exitcode.Err).Code)

output, err := io.ReadAll(logFile)
require.NoError(t, err)

assert.Contains(t, string(output), "panicked")
}

func TestRunCmd_Panic_Verbose(t *testing.T) {
testServerURL, router, tearDown := setupTestServer()
defer tearDown()

version.OS = "some os"
version.Arch = "some architecture"
version.Version = "some version"

router.HandleFunc("/plugins/errors", func(w http.ResponseWriter, req *http.Request) {
// check request
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, []string{"Basic MDAwMDAwMDAtMDAwMC00MDAwLTgwMDAtMDAwMDAwMDAwMDAw"}, req.Header["Authorization"])
assert.Equal(t, []string{"application/json"}, req.Header["Content-Type"])

expectedBodyTpl, err := os.ReadFile("testdata/diagnostics_request_template.json")
require.NoError(t, err)

body, err := io.ReadAll(req.Body)
require.NoError(t, err)

var diagnostics struct {
Architecture string `json:"architecture"`
CliVersion string `json:"cli_version"`
Editor string `json:"editor"`
Logs string `json:"logs"`
OriginalError string `json:"error_message"`
Platform string `json:"platform"`
Plugin string `json:"plugin"`
Stack string `json:"stacktrace"`
}

err = json.Unmarshal(body, &diagnostics)
require.NoError(t, err)

expectedBodyStr := fmt.Sprintf(
string(expectedBodyTpl),
jsonEscape(t, diagnostics.OriginalError),
jsonEscape(t, diagnostics.Logs),
jsonEscape(t, diagnostics.Stack),
)

assert.JSONEq(t, expectedBodyStr, string(body))

// send response
w.WriteHeader(http.StatusCreated)
})

logFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

defer logFile.Close()

ctx := context.Background()

v := viper.New()
v.Set("api-url", testServerURL)
v.Set("log-file", logFile.Name())

logger, err := SetupLogging(ctx, v)
require.NoError(t, err)

defer logger.Flush()

ctx = log.ToContext(ctx, logger)

err = runCmd(ctx, v, true, false, func(_ context.Context, _ *viper.Viper) (int, error) {
panic("fail")
})

var errexitcode exitcode.Err

require.ErrorAs(t, err, &errexitcode)
assert.Equal(t, exitcode.ErrGeneric, err.(exitcode.Err).Code)

output, err := io.ReadAll(logFile)
require.NoError(t, err)

assert.Contains(t, string(output), "panicked")
}

func TestRunCmd_ErrOfflineEnqueue(t *testing.T) {
testServerURL, router, tearDown := setupTestServer()
defer tearDown()
Expand Down

0 comments on commit 265065a

Please sign in to comment.