Skip to content

Commit

Permalink
[progress] Add settings validation
Browse files Browse the repository at this point in the history
  • Loading branch information
andyone committed Oct 19, 2023
1 parent c31226c commit 340e201
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* `[fmtutil/panel]` Added `TOP_LINE` option
* `[fmtutil/panel]` Added `DefaultOptions` variable to set default options for all panels
* `[strutil]` Added method `LenVisual`
* `[progress]` Added settings validation
* `[usage]` Added color tag validation
* `[fmtutil/panel]` Improved panel rendering when `BOTTOM_LINE` option is used
* `[fmtutil/panel]` Improved panel rendering when `label` is empty
Expand Down
75 changes: 61 additions & 14 deletions progress/progress.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import (
// MIN_WIDTH is minimal progress bar width
const MIN_WIDTH = 80

// MIN_REFRESH_RATE is minimal refresh rate (1 ms)
const MIN_REFRESH_RATE = time.Duration(time.Millisecond)

// PROGRESS_BAR_SYMBOL is symbol for creating progress bar
const PROGRESS_BAR_SYMBOL = "—"

Expand Down Expand Up @@ -120,6 +123,10 @@ var DefaultSettings = Settings{
WindowSizeSec: 15.0,
}

var (
ErrBarIsNil = fmt.Errorf("Progress bar struct is nil")
)

// ////////////////////////////////////////////////////////////////////////////////// //

// New creates new progress bar struct
Expand All @@ -135,13 +142,13 @@ func New(total int64, name string) *Bar {
// ////////////////////////////////////////////////////////////////////////////////// //

// Start starts progress processing
func (b *Bar) Start() {
func (b *Bar) Start() error {
if b == nil {
return
return ErrBarIsNil
}

if b.IsStarted() && !b.IsFinished() {
return
return nil
}

b.phCounter = 0
Expand All @@ -151,12 +158,7 @@ func (b *Bar) Start() {
b.startTime = time.Now()
b.finishChan = make(chan bool)
b.finishGroup = sync.WaitGroup{}

if b.settings.RefreshRate >= time.Millisecond {
b.ticker = time.NewTicker(b.settings.RefreshRate)
} else {
b.ticker = time.NewTicker(100 * time.Millisecond)
}
b.ticker = time.NewTicker(b.settings.RefreshRate)

if b.total > 0 {
b.passThruCalc = NewPassThruCalc(
Expand All @@ -165,37 +167,49 @@ func (b *Bar) Start() {
}

go b.renderer()

return nil
}

// Finish finishes progress processing
func (b *Bar) Finish() {
func (b *Bar) Finish() error {
if b == nil {
return
return ErrBarIsNil
}

b.mu.RLock()

if b.finished || !b.started {
b.mu.RUnlock()
return
return nil
}

b.mu.RUnlock()

b.finishGroup.Add(1)
b.finishChan <- true
b.finishGroup.Wait()

return nil
}

// UpdateSettings updates progress settings
func (b *Bar) UpdateSettings(s Settings) {
func (b *Bar) UpdateSettings(s Settings) error {
if b == nil {
return
return ErrBarIsNil
}

err := s.Validate()

if err != nil {
return err
}

b.mu.Lock()
b.settings = s
b.mu.Unlock()

return nil
}

// SetName sets progress bar name
Expand Down Expand Up @@ -632,6 +646,39 @@ func (b *Bar) renderPlaceholder(size int) string {

// ////////////////////////////////////////////////////////////////////////////////// //

// Validate validates settings struct
func (s Settings) Validate() error {
switch {
case !fmtc.IsTag(s.NameColorTag):
return fmt.Errorf("NameColorTag value is not a valid color tag")

case !fmtc.IsTag(s.BarFgColorTag):
return fmt.Errorf("BarFgColorTag value is not a valid color tag")

case !fmtc.IsTag(s.BarBgColorTag):
return fmt.Errorf("BarBgColorTag value is not a valid color tag")

case !fmtc.IsTag(s.PercentColorTag):
return fmt.Errorf("PercentColorTag value is not a valid color tag")

case !fmtc.IsTag(s.ProgressColorTag):
return fmt.Errorf("ProgressColorTag value is not a valid color tag")

case !fmtc.IsTag(s.SpeedColorTag):
return fmt.Errorf("SpeedColorTag value is not a valid color tag")

case !fmtc.IsTag(s.RemainingColorTag):
return fmt.Errorf("RemainingColorTag value is not a valid color tag")

case s.RefreshRate != 0 && s.RefreshRate < MIN_REFRESH_RATE:
return fmt.Errorf("RefreshRate too small (less than 1ms)")
}

return nil
}

// ////////////////////////////////////////////////////////////////////////////////// //

// Read reads data and updates progress bar
func (r *passThruReader) Read(p []byte) (int, error) {
n, err := r.Reader.Read(p)
Expand Down
41 changes: 37 additions & 4 deletions progress/progress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,15 @@ func (s *ProgressSuite) TestBar(c *C) {

pbs := DefaultSettings
pbs.Width = 60
pbs.RefreshRate = time.Microsecond

err := pb.UpdateSettings(pbs)
c.Assert(err, NotNil)

pbs.RefreshRate = time.Millisecond

pb.UpdateSettings(pbs)
err = pb.UpdateSettings(pbs)
c.Assert(err, IsNil)

pb.SetName("ABC")
c.Assert(pb.Name(), Equals, "ABC")
Expand Down Expand Up @@ -87,9 +93,6 @@ func (s *ProgressSuite) TestBar(c *C) {
pb.Finish() // should be skipped (not started)
c.Assert(pb.IsFinished(), Equals, false)

pbs.RefreshRate = 0
pb.UpdateSettings(pbs)

pb.Start()
pb.renderElements(false)

Expand All @@ -107,6 +110,36 @@ func (s *ProgressSuite) TestBar(c *C) {
pb.Finish()
}

func (s *ProgressSuite) TestSettingsValidation(c *C) {
pbs := DefaultSettings

c.Assert(pbs.Validate(), IsNil)

pbs.RefreshRate = 2
c.Assert(pbs.Validate().Error(), Equals, "RefreshRate too small (less than 1ms)")

pbs.RemainingColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "RemainingColorTag value is not a valid color tag")

pbs.SpeedColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "SpeedColorTag value is not a valid color tag")

pbs.ProgressColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "ProgressColorTag value is not a valid color tag")

pbs.PercentColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "PercentColorTag value is not a valid color tag")

pbs.BarBgColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "BarBgColorTag value is not a valid color tag")

pbs.BarFgColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "BarFgColorTag value is not a valid color tag")

pbs.NameColorTag = "{ABCD}"
c.Assert(pbs.Validate().Error(), Equals, "NameColorTag value is not a valid color tag")
}

func (s *ProgressSuite) TestBarRender(c *C) {
pb := New(100, "ABCD")
c.Assert(pb, NotNil)
Expand Down

0 comments on commit 340e201

Please sign in to comment.