Skip to content

Commit

Permalink
Adding gosec and lint, fixing null_type overflow
Browse files Browse the repository at this point in the history
ChangeLog:
  - Adding gosec linting
  - Adding static type to enum
  - fixing nulltype overflow
  - Trying out gotestsum as an alternative to go-junit-report.xml
  • Loading branch information
safaci2000 committed Oct 10, 2024
1 parent f9358ca commit 974882f
Show file tree
Hide file tree
Showing 16 changed files with 192 additions and 83 deletions.
21 changes: 13 additions & 8 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
build_and_tests:
docker:
# specify the version
- image: cimg/go:1.21.6
- image: cimg/go:1.22.0
- image: cimg/postgres:14.10
environment:
POSTGRES_USER: jet
Expand Down Expand Up @@ -129,16 +129,21 @@ jobs:
# to create test results report
- run:
name: Install go-junit-report
command: go install github.com/jstemmer/go-junit-report@latest

command: go install github.com/jstemmer/go-junit-report/[email protected]
- run:
name: Install gotestsum
command: go install gotest.tools/gotestsum@latest
- run: mkdir -p $TEST_RESULTS

# this will run all tests and exclude test files from code coverage report
- run: |
go test -v ./... \
-covermode=atomic \
-coverpkg=github.com/go-jet/jet/v2/postgres/...,github.com/go-jet/jet/v2/mysql/...,github.com/go-jet/jet/v2/sqlite/...,github.com/go-jet/jet/v2/qrm/...,github.com/go-jet/jet/v2/generator/...,github.com/go-jet/jet/v2/internal/... \
-coverprofile=cover.out 2>&1 | go-junit-report > $TEST_RESULTS/results.xml
- run:
name: Running tests
command: gotestsum --junitfile report.xml --format testname
#- run: |
# go test -v ./... \
# -covermode=atomic \
# -coverpkg=github.com/go-jet/jet/v2/postgres/...,github.com/go-jet/jet/v2/mysql/...,github.com/go-jet/jet/v2/sqlite/...,github.com/go-jet/jet/v2/qrm/...,github.com/go-jet/jet/v2/generator/...,github.com/go-jet/jet/v2/internal/... \
# -coverprofile=cover.out 2>&1 | go-junit-report > $TEST_RESULTS/results.xml

# run mariaDB and cockroachdb tests. No need to collect coverage, because coverage is already included with mysql and postgres tests
- run: MY_SQL_SOURCE=MariaDB go test -v ./tests/mysql/
Expand Down
48 changes: 48 additions & 0 deletions .github/workflows/code_scanner.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
name: Code Scanners
on:
push:
branches:
- master
pull_request:
branches:
- master

env:
GO_VERSION: 1.22.0


permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
# pull-requests: read


jobs:
security_scanning:
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.22.0
cache: true
- name: Setup Tools
run: |
go install github.com/securego/gosec/v2/cmd/gosec@latest
- name: Running Scan
run: gosec --exclude=G402,G304 ./...
lint_scanner:
runs-on: ubuntu-latest
steps:
- name: Checkout Source
uses: actions/checkout@v4
- uses: actions/setup-go@v5
with:
go-version: 1.22.0
cache: true
- name: Setup Tools
run: |
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
- name: Running Scan
run: golangci-lint run --timeout=30m ./...
19 changes: 19 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
run:
# The default concurrency value is the number of available CPU.
concurrency: 4
# Timeout for analysis, e.g. 30s, 5m.
# Default: 1m
timeout: 30m
# Exit code when at least one issue was found.
# Default: 1
issues-exit-code: 2
# Include test files or not.
# Default: true
tests: false

issues:
exclude-dirs:
- tests
exclude-files:
- "_test.go"
- "testutils.go"
2 changes: 1 addition & 1 deletion examples/quick-start/quick-start.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func main() {
func jsonSave(path string, v interface{}) {
jsonText, _ := json.MarshalIndent(v, "", "\t")

err := os.WriteFile(path, jsonText, 0644)
err := os.WriteFile(path, jsonText, 0600)

panicOnError(err)
}
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
module github.com/go-jet/jet/v2

go 1.18
go 1.22.0

require (
github.com/go-sql-driver/mysql v1.8.1
github.com/google/go-cmp v0.6.0
github.com/google/uuid v1.6.0
github.com/jackc/pgconn v1.14.3
github.com/jackc/pgtype v1.14.3
github.com/jackc/pgx/v4 v4.18.3
github.com/lib/pq v1.10.9
github.com/mattn/go-sqlite3 v1.14.17
)

require (
github.com/google/go-cmp v0.6.0
github.com/jackc/pgtype v1.14.3
github.com/jackc/pgx/v4 v4.18.3
github.com/pkg/profile v1.7.0
github.com/shopspring/decimal v1.4.0
github.com/stretchr/testify v1.9.0
Expand Down
2 changes: 1 addition & 1 deletion internal/jet/statement.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func duration(f func()) time.Duration {

f()

return time.Now().Sub(start)
return time.Since(start)
}

// ExpressionStatement interfacess
Expand Down
7 changes: 4 additions & 3 deletions internal/testutils/test_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,12 @@ func AssertJSON(t *testing.T, data interface{}, expectedJSON string) {
}

// SaveJSONFile saves v as json at testRelativePath
// nolint:unused
func SaveJSONFile(v interface{}, testRelativePath string) {
jsonText, _ := json.MarshalIndent(v, "", "\t")

filePath := getFullPath(testRelativePath)
err := os.WriteFile(filePath, jsonText, 0644)
err := os.WriteFile(filePath, jsonText, 0600)

throw.OnError(err)
}
Expand All @@ -116,7 +117,7 @@ func SaveJSONFile(v interface{}, testRelativePath string) {
func AssertJSONFile(t *testing.T, data interface{}, testRelativePath string) {

filePath := getFullPath(testRelativePath)
fileJSONData, err := os.ReadFile(filePath)
fileJSONData, err := os.ReadFile(filePath) // #nosec G304
require.NoError(t, err)

if runtime.GOOS == "windows" {
Expand Down Expand Up @@ -243,7 +244,7 @@ func AssertQueryPanicErr(t *testing.T, stmt jet.Statement, db qrm.DB, dest inter

// AssertFileContent check if file content at filePath contains expectedContent text.
func AssertFileContent(t *testing.T, filePath string, expectedContent string) {
enumFileData, err := os.ReadFile(filePath)
enumFileData, err := os.ReadFile(filePath) // #nosec G304

require.NoError(t, err)

Expand Down
10 changes: 7 additions & 3 deletions internal/utils/filesys/filesys.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package filesys

import (
"errors"
"fmt"
"go/format"
"os"
Expand All @@ -16,7 +17,7 @@ func FormatAndSaveGoFile(dirPath, fileName string, text []byte) error {
newGoFilePath += ".go"
}

file, err := os.Create(newGoFilePath)
file, err := os.Create(newGoFilePath) // #nosec 304

if err != nil {
return err
Expand All @@ -28,7 +29,10 @@ func FormatAndSaveGoFile(dirPath, fileName string, text []byte) error {

// if there is a format error we will write unformulated text for debug purposes
if err != nil {
file.Write(text)
_, writeErr := file.Write(text)
if writeErr != nil {
return errors.Join(writeErr, fmt.Errorf("failed to format '%s', check '%s' for syntax errors: %w", fileName, newGoFilePath, err))
}
return fmt.Errorf("failed to format '%s', check '%s' for syntax errors: %w", fileName, newGoFilePath, err)
}

Expand All @@ -43,7 +47,7 @@ func FormatAndSaveGoFile(dirPath, fileName string, text []byte) error {
// EnsureDirPathExist ensures dir path exists. If path does not exist, creates new path.
func EnsureDirPathExist(dirPath string) error {
if _, err := os.Stat(dirPath); os.IsNotExist(err) {
err := os.MkdirAll(dirPath, os.ModePerm)
err := os.MkdirAll(dirPath, 0o750)

if err != nil {
return fmt.Errorf("can't create directory - %s: %w", dirPath, err)
Expand Down
38 changes: 19 additions & 19 deletions mysql/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,25 @@ type unitType string
// List of interval unit types for MySQL
const (
MICROSECOND unitType = "MICROSECOND"
SECOND = "SECOND"
MINUTE = "MINUTE"
HOUR = "HOUR"
DAY = "DAY"
WEEK = "WEEK"
MONTH = "MONTH"
QUARTER = "QUARTER"
YEAR = "YEAR"
SECOND_MICROSECOND = "SECOND_MICROSECOND"
MINUTE_MICROSECOND = "MINUTE_MICROSECOND"
MINUTE_SECOND = "MINUTE_SECOND"
HOUR_MICROSECOND = "HOUR_MICROSECOND"
HOUR_SECOND = "HOUR_SECOND"
HOUR_MINUTE = "HOUR_MINUTE"
DAY_MICROSECOND = "DAY_MICROSECOND"
DAY_SECOND = "DAY_SECOND"
DAY_MINUTE = "DAY_MINUTE"
DAY_HOUR = "DAY_HOUR"
YEAR_MONTH = "YEAR_MONTH"
SECOND unitType = "SECOND"
MINUTE unitType = "MINUTE"
HOUR unitType = "HOUR"
DAY unitType = "DAY"
WEEK unitType = "WEEK"
MONTH unitType = "MONTH"
QUARTER unitType = "QUARTER"
YEAR unitType = "YEAR"
SECOND_MICROSECOND unitType = "SECOND_MICROSECOND"
MINUTE_MICROSECOND unitType = "MINUTE_MICROSECOND"
MINUTE_SECOND unitType = "MINUTE_SECOND"
HOUR_MICROSECOND unitType = "HOUR_MICROSECOND"
HOUR_SECOND unitType = "HOUR_SECOND"
HOUR_MINUTE unitType = "HOUR_MINUTE"
DAY_MICROSECOND unitType = "DAY_MICROSECOND"
DAY_SECOND unitType = "DAY_SECOND"
DAY_MINUTE unitType = "DAY_MINUTE"
DAY_HOUR unitType = "DAY_HOUR"
YEAR_MONTH unitType = "YEAR_MONTH"
)

// Interval is representation of MySQL interval
Expand Down
37 changes: 28 additions & 9 deletions qrm/internal/null_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ import (
"time"
)

var (
castOverFlowError = fmt.Errorf("cannot cast a negative value to an unsigned value, buffer overflow error")
)

// NullBool struct
type NullBool struct {
sql.NullBool
Expand Down Expand Up @@ -119,30 +123,45 @@ func (n *NullUInt64) Scan(value interface{}) error {
n.Valid = false
return nil
case int64:
if v < 0 {
return castOverFlowError
}
n.UInt64, n.Valid = uint64(v), true
return nil
case uint64:
n.UInt64, n.Valid = v, true
return nil
case int32:
if v < 0 {
return castOverFlowError
}
n.UInt64, n.Valid = uint64(v), true
return nil
case uint32:
case int16:
if v < 0 {
return castOverFlowError
}
n.UInt64, n.Valid = uint64(v), true
return nil
case int16:
case int8:
if v < 0 {
return castOverFlowError
}
n.UInt64, n.Valid = uint64(v), true
return nil
case uint16:
case int:
if v < 0 {
return castOverFlowError
}
n.UInt64, n.Valid = uint64(v), true
return nil
case int8:
case uint64:
n.UInt64, n.Valid = v, true
return nil
case uint32:
n.UInt64, n.Valid = uint64(v), true
return nil
case uint8:
case uint16:
n.UInt64, n.Valid = uint64(v), true
return nil
case int:
case uint8:
n.UInt64, n.Valid = uint64(v), true
return nil
case uint:
Expand Down
36 changes: 36 additions & 0 deletions qrm/internal/null_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package internal

import (
"fmt"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
"time"
Expand Down Expand Up @@ -62,11 +63,21 @@ func TestNullUInt64(t *testing.T) {
value, _ := nullUInt64.Value()
require.Equal(t, value, uint64(11))

require.NoError(t, nullUInt64.Scan(uint64(11)))
require.Equal(t, nullUInt64.Valid, true)
value, _ = nullUInt64.Value()
require.Equal(t, value, uint64(11))

require.NoError(t, nullUInt64.Scan(int32(32)))
require.Equal(t, nullUInt64.Valid, true)
value, _ = nullUInt64.Value()
require.Equal(t, value, uint64(32))

require.NoError(t, nullUInt64.Scan(uint32(32)))
require.Equal(t, nullUInt64.Valid, true)
value, _ = nullUInt64.Value()
require.Equal(t, value, uint64(32))

require.NoError(t, nullUInt64.Scan(int16(20)))
require.Equal(t, nullUInt64.Valid, true)
value, _ = nullUInt64.Value()
Expand All @@ -88,4 +99,29 @@ func TestNullUInt64(t *testing.T) {
require.Equal(t, value, uint64(30))

require.Error(t, nullUInt64.Scan("text"), "can't scan int32 from text")

//Validate negative use cases
err := nullUInt64.Scan(int64(-5))
assert.NotNil(t, err)
assert.Error(t, err, castOverFlowError)

//Validate negative use cases
err = nullUInt64.Scan(-5)
assert.NotNil(t, err)
assert.Error(t, err, castOverFlowError)

//Validate negative use cases
err = nullUInt64.Scan(int32(-5))
assert.NotNil(t, err)
assert.Error(t, err, castOverFlowError)

//Validate negative use cases
err = nullUInt64.Scan(int16(-5))
assert.NotNil(t, err)
assert.Error(t, err, castOverFlowError)

//Validate negative use cases
err = nullUInt64.Scan(int8(-5))
assert.NotNil(t, err)
assert.Error(t, err, castOverFlowError)
}
Loading

0 comments on commit 974882f

Please sign in to comment.