Skip to content

Commit

Permalink
Merge pull request #26 from dreitier/bugfix/number_format_of_large_nu…
Browse files Browse the repository at this point in the history
…mbers_is_wrong

Bugfix/number format of large numbers is wrong
  • Loading branch information
thomashoell authored Nov 27, 2023
2 parents 99c1760 + bdaad30 commit 3563be8
Show file tree
Hide file tree
Showing 11 changed files with 176 additions and 92 deletions.
8 changes: 6 additions & 2 deletions _samples/1.postgres-dumps/backup_definitions.yaml
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
'./backups':
backups:
alias: my-backups
fuse:
defaults:
schedule: 0 2 * * *
retention-count: 10
retention-age: 7d
files:
'dump-%Y%M%D.sql':
dump-%Y%M%D.sql:
alias: pgdump
schedule: 0 1 * * *
sort: interpolation
10 changes: 10 additions & 0 deletions _samples/1.postgres-dumps/backup_definitions_faulty.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
backups:
alias: my-backups
fuse:
defaults:
schedule: 0 02 * * *
files:
dump-%Y%M%D.sql:
alias: pgdump
schedule: 0 1 * * *
sort: interpolation
15 changes: 15 additions & 0 deletions backup/cron_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,21 @@ func Test_FindPrevious(t *testing.T) {
}
}

func Test_FindPrevious_2(t *testing.T) {
cron := cronexpr.MustParse("5 4 * * *")
loc := time.Local
timestamp := time.Date(2023, 11, 23, 10, 41, 30, 0, loc)

result := FindPrevious(cron, timestamp)

expected := time.Date(2023, 11, 23, 4, 5, 0, 0, loc)

if !result.Equal(expected) {
t.Errorf("Calculated execution time does not match expected execution time.\n"+
"Expected: [%s], Actual: [%s]", expected.String(), result.String())
}
}

func Test_FindPreviousWithWeekDays(t *testing.T) {
cron := cronexpr.MustParse("30 23 * * MON-FRI")
loc := time.Local
Expand Down
47 changes: 47 additions & 0 deletions backup/definitions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@ package backup

import (
"github.com/davecgh/go-spew/spew"
"github.com/gorhill/cronexpr"
"github.com/stretchr/testify/assert"
"io"
"os"
"testing"
"time"
)

func Test_parseDefinitions(t *testing.T) {
assertion := assert.New(t)
definitionsFile, err := os.Open("../_samples/1.postgres-dumps/backup_definitions.yaml")

if err != nil {
t.Fatal(err)
}
Expand All @@ -27,6 +31,35 @@ func Test_parseDefinitions(t *testing.T) {
if defs == nil {
t.Error("parsed definitions object is nil")
}

assertion.Equal("my-backups", defs["backups"].Alias)
assertion.Equal(cronexpr.MustParse("0 2 * * *"), defs["backups"].Defaults.Schedule)
assertion.Equal(uint64(10), defs["backups"].Defaults.RetentionCount)
assertion.Equal(7*24*time.Hour, defs["backups"].Defaults.RetentionAge)
assertion.Equal(false, defs["backups"].Defaults.Purge)
assertion.Equal("pgdump", defs["backups"].Files["dump-%Y%M%D.sql"].Alias)
assertion.Equal(cronexpr.MustParse("0 1 * * *"), defs["backups"].Files["dump-%Y%M%D.sql"].Schedule)
assertion.Equal(uint64(10), defs["backups"].Files["dump-%Y%M%D.sql"].RetentionCount)
assertion.Equal(7*24*time.Hour, defs["backups"].Files["dump-%Y%M%D.sql"].RetentionAge)
}

func Test_parseFaultyDefinitions_expectError(t *testing.T) {
definitionsFile, err := os.Open("../_samples/1.postgres-dumps/backup_definitions_faulty.yaml")
if err != nil {
t.Fatal(err)
}

defer func(definitionsFile *os.File) {
_ = definitionsFile.Close()
}(definitionsFile)

reader := io.Reader(definitionsFile)

_, err = ParseRawDefinitions(reader)

if err == nil {
t.Error("parsed definitions file contains an error, failure was expected")
}
}

func Test_parseDirectoryPattern(t *testing.T) {
Expand Down Expand Up @@ -138,6 +171,20 @@ func Test_parseFilenamePattern(t *testing.T) {
}
}

func Test_parseFilenamePattern2(t *testing.T) {
const fileNamePattern = "%Y-%M-%D.tar.gz"
const fileNameMatch = "2023-11-14.tar.gz"

regex, err := ParseFilePattern(fileNamePattern)
if err != nil {
t.Fatal(err)
}

if !regex.MatchString(fileNameMatch) {
t.Error("Regex did not match a correct patten:", fileNameMatch)
}
}

func TestSplitPattern_extractsToVariables(t *testing.T) {
assertion := assert.New(t)

Expand Down
7 changes: 5 additions & 2 deletions backup/raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,13 @@ func parseDefaults(cfg config.Raw) (*Defaults, error) {
return nil, nil
}

schedule, err := cronexpr.Parse(cfg.String("schedule"))
cronExprString := cfg.String("schedule")
log.Debugf("parsed cron expression is: %s", cronExprString)
schedule, err := cronexpr.Parse(cronExprString)

if err != nil {
return nil, nil
log.Errorf("failed to parse cron expression [%s]: %s", cronExprString, err)
return nil, err
}

defaults := &Defaults{
Expand Down
6 changes: 3 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ func ParseDisksSection(cfg Raw) *DisksConfiguration {
const paramAllOthersValueExclude = paramExclude

// #5:UC2: include is the default behaviour
allOthers := DISKS_BEHAVIOUR_INCLUDE
allOthers := DisksBehaviourInclude

if cfg.Has(paramAllOthers) {
rawAllOthers := cfg.String(paramAllOthers)

switch rawAllOthers {
case paramAllOthersValueInclude:
allOthers = DISKS_BEHAVIOUR_INCLUDE
allOthers = DisksBehaviourInclude
break
case paramAllOthersValueExclude:
allOthers = DISKS_BEHAVIOUR_EXCLUDE
allOthers = DisksBehaviourExclude
break
default:
log.Warnf("Unknown value for %s. Using 'include' as default value", paramAllOthers)
Expand Down
52 changes: 26 additions & 26 deletions config/disks.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,26 @@ import (

// behaviour enum
const (
DISKS_BEHAVIOUR_INCLUDE = iota
DISKS_BEHAVIOUR_EXCLUDE = iota
DisksBehaviourInclude = iota
DisksBehaviourExclude = iota
)

// applied policy enum
const (
DISKS_POLICY_INCLUDE = "explicit_include_policy"
DISKS_POLICY_INCLUDE_BY_REGEX = "explicit_include_by_regex_policy"
DISKS_POLICY_EXCLUDE = "explicit_exclude_policy"
DISKS_POLICY_EXCLUDE_BY_REGEX = "explicit_exclude_by_regex_policy"
DISKS_POLICY_CONFLICTING = "unallowed_definition_in_include_and_exclude_policy"
DISKS_POLICY_CONFLICTING_BY_REGEX = "unallowed_definition_in_include_or_exclude_and_contradicting_regexp"
DISKS_POLICY_NO_MATCH_FALLBACK = "not_matching_fallback_to_all_others"
DisksPolicyInclude = "explicit_include_policy"
DisksPolicyIncludeByRegex = "explicit_include_by_regex_policy"
DisksPolicyExclude = "explicit_exclude_policy"
DisksPolicyExcludeByRegex = "explicit_exclude_by_regex_policy"
DisksPolicyConflicting = "unallowed_definition_in_include_and_exclude_policy"
DisksPolicyConflictingByRegex = "unallowed_definition_in_include_or_exclude_and_contradicting_regexp"
DisksPolicyNoMatchFallback = "not_matching_fallback_to_all_others"
)

// this is the transformed outcome of the `disks:` section
// DisksConfiguration this is the transformed outcome of the `disks:` section
type DisksConfiguration struct {
// simple disknames can be identified through a lookup table
include map[string]SingleDiskConfiguration
// for regexps we cannot use a lookup table but have execute each regex
// for regexps, we cannot use a lookup table but have execute each regex
includeRegExps []SingleDiskConfiguration
exclude map[string]SingleDiskConfiguration
excludeRegExps []SingleDiskConfiguration
Expand All @@ -42,7 +42,7 @@ type SingleDiskConfiguration struct {
IsRegularExpression bool
}

// Create a new SingleDiskConfiguration
// NewSingleDiskConfiguration Create a new SingleDiskConfiguration
// @return error if the diskNameOrRegExp is based upon a regex ('/someregex/')
func NewSingleDiskConfiguration(diskNameOrRegExp string) (*SingleDiskConfiguration, error) {
// we are checking if the given diskName to include or exclude is a regular expression like "/.*/"
Expand All @@ -65,15 +65,15 @@ func NewSingleDiskConfiguration(diskNameOrRegExp string) (*SingleDiskConfigurati
return r, nil
}

func (self *DisksConfiguration) GetIncludedDisks() map[string]SingleDiskConfiguration {
return self.include
func (diskConfig *DisksConfiguration) GetIncludedDisks() map[string]SingleDiskConfiguration {
return diskConfig.include
}

// Return true if the given disk is defined as "included" through some policy
func (self *DisksConfiguration) IsDiskIncluded(diskName string) bool {
status, appliedPolicy := GetDiskStatus(diskName, self)
// IsDiskIncluded Return true if the given disk is defined as "included" through some policy
func (diskConfig *DisksConfiguration) IsDiskIncluded(diskName string) bool {
status, appliedPolicy := GetDiskStatus(diskName, diskConfig)

if status == DISKS_BEHAVIOUR_EXCLUDE {
if status == DisksBehaviourExclude {
log.Debugf("Disk %s is excluded (%s)", diskName, appliedPolicy)

return false
Expand Down Expand Up @@ -105,7 +105,7 @@ func hasAtLeastOneMatch(diskName string, possibleConfigsWithRegExps []SingleDisk
return false
}

// Calculate the disk's status based upon the defined policies
// GetDiskStatus Calculate the disk's status based upon the defined policies
// @return (status, appliedPolicy)
func GetDiskStatus(diskName string, disksConfiguration *DisksConfiguration) ( /* status */ int /* appliedPolicy */, string) {
_, isExplicitlyIncluded := disksConfiguration.include[diskName]
Expand All @@ -118,33 +118,33 @@ func GetDiskStatus(diskName string, disksConfiguration *DisksConfiguration) ( /*

// include
if isExplicitlyIncluded && !isExcluded {
return DISKS_BEHAVIOUR_INCLUDE, DISKS_POLICY_INCLUDE
return DisksBehaviourInclude, DisksPolicyInclude
}

// included by regex
if isIncludedByRegex && !isExcluded {
return DISKS_BEHAVIOUR_INCLUDE, DISKS_POLICY_INCLUDE_BY_REGEX
return DisksBehaviourInclude, DisksPolicyIncludeByRegex
}

// exclude
if isExplicitlyExcluded && !isIncluded {
return DISKS_BEHAVIOUR_EXCLUDE, DISKS_POLICY_EXCLUDE
return DisksBehaviourExclude, DisksPolicyExclude
}

// excluded by regex
if isExcludedByRegex && !isIncluded {
return DISKS_BEHAVIOUR_EXCLUDE, DISKS_POLICY_EXCLUDE_BY_REGEX
return DisksBehaviourExclude, DisksPolicyExcludeByRegex
}

if isExplicitlyIncluded && isExplicitlyExcluded {
return disksConfiguration.behaviourForAllOthers, DISKS_POLICY_CONFLICTING
return disksConfiguration.behaviourForAllOthers, DisksPolicyConflicting
}

// disk has been defined in both `include` and `exclude` sections
if isIncluded && isExcluded {
return disksConfiguration.behaviourForAllOthers, DISKS_POLICY_CONFLICTING_BY_REGEX
return disksConfiguration.behaviourForAllOthers, DisksPolicyConflictingByRegex
}

// this applies to a disk which has no match
return disksConfiguration.behaviourForAllOthers, DISKS_POLICY_NO_MATCH_FALLBACK
return disksConfiguration.behaviourForAllOthers, DisksPolicyNoMatchFallback
}
38 changes: 19 additions & 19 deletions config/disks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ exclude:

status, appliedPolicy := GetDiskStatus("a", cfg)

assertion.Equal(DISKS_POLICY_EXCLUDE, appliedPolicy)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DisksPolicyExclude, appliedPolicy)
assertion.Equal(DisksBehaviourExclude, status)
}

func Test_GetDiskStatus_GH5_UC2_1_allOthersExplicitlyIncluded(t *testing.T) {
Expand All @@ -53,13 +53,13 @@ all_others: include
cfg := ParseDisksSection(raw)

status, _ := GetDiskStatus("bucket-1", cfg)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DisksBehaviourExclude, status)

status, _ = GetDiskStatus("bucket-2", cfg)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE, status)
assertion.Equal(DisksBehaviourInclude, status)

status, _ = GetDiskStatus("bucket-3", cfg)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE, status)
assertion.Equal(DisksBehaviourInclude, status)
}

func Test_GetDiskStatus_GH5_UC2_2_allOthersImplicitlyIncluded(t *testing.T) {
Expand All @@ -74,13 +74,13 @@ include:
cfg := ParseDisksSection(raw)

status, _ := GetDiskStatus("bucket-1", cfg)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DisksBehaviourExclude, status)

status, _ = GetDiskStatus("bucket-2", cfg)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE, status)
assertion.Equal(DisksBehaviourInclude, status)

status, _ = GetDiskStatus("bucket-3", cfg)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE, status)
assertion.Equal(DisksBehaviourInclude, status)
}

func Test_GetDiskStatus_GH5_UC3_allOthersExplicitlyExcluded(t *testing.T) {
Expand All @@ -96,13 +96,13 @@ all_others: exclude
cfg := ParseDisksSection(raw)

status, _ := GetDiskStatus("bucket-1", cfg)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DisksBehaviourExclude, status)

status, _ = GetDiskStatus("bucket-2", cfg)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE, status)
assertion.Equal(DisksBehaviourInclude, status)

status, _ = GetDiskStatus("bucket-3", cfg)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DisksBehaviourExclude, status)

spew.Dump(raw)
}
Expand All @@ -121,8 +121,8 @@ all_others: exclude
cfg := ParseDisksSection(raw)

status, appliedPolicy := GetDiskStatus("bucket-2", cfg)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DISKS_POLICY_CONFLICTING, appliedPolicy)
assertion.Equal(DisksBehaviourExclude, status)
assertion.Equal(DisksPolicyConflicting, appliedPolicy)
}

func Test_GetDiskStatus_GH6_UC1_excludedByRegex(t *testing.T) {
Expand All @@ -136,8 +136,8 @@ exclude:

status, appliedPolicy := GetDiskStatus("abcdef", cfg)

assertion.Equal(DISKS_POLICY_EXCLUDE_BY_REGEX, appliedPolicy)
assertion.Equal(DISKS_BEHAVIOUR_EXCLUDE, status)
assertion.Equal(DisksPolicyExcludeByRegex, appliedPolicy)
assertion.Equal(DisksBehaviourExclude, status)
}

func Test_GetDiskStatus_GH6_UC1_includedByRegex(t *testing.T) {
Expand All @@ -151,8 +151,8 @@ include:

status, appliedPolicy := GetDiskStatus("abcdef", cfg)

assertion.Equal(DISKS_POLICY_INCLUDE_BY_REGEX, appliedPolicy)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE, status)
assertion.Equal(DisksPolicyIncludeByRegex, appliedPolicy)
assertion.Equal(DisksBehaviourInclude, status)
}

func Test_GetDiskStatus_GH6_UC1_whenRegExpsForInclude_AND_excludeMatches_itFallsBackToDefaultBehaviour(t *testing.T) {
Expand All @@ -168,6 +168,6 @@ exclude:

status, appliedPolicy := GetDiskStatus("abcdef", cfg)

assertion.Equal(DISKS_POLICY_CONFLICTING_BY_REGEX, appliedPolicy)
assertion.Equal(DISKS_BEHAVIOUR_INCLUDE /* default behaviour */, status)
assertion.Equal(DisksPolicyConflictingByRegex, appliedPolicy)
assertion.Equal(DisksBehaviourInclude /* default behaviour */, status)
}
Loading

0 comments on commit 3563be8

Please sign in to comment.