Backport from dev

This commit is contained in:
kayos@tcp.direct 2022-09-11 04:32:45 -07:00
parent 2cc7fa6ac1
commit dd1a3a703b
Signed by: kayos
GPG Key ID: 4B841471B4BEE979
7 changed files with 16 additions and 294 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ HellPot
*.save
*.toml
*.yaml
.backups/

View File

@ -1,28 +0,0 @@
package heffalump
import (
"errors"
"io"
"testing"
"github.com/yunginnanet/HellPot/internal/util"
)
func TestHeffalump_WriteHell(t *testing.T) {
sp := util.NewCappedSpeedometer(io.Discard, 55555)
var err error
var count int64
for err == nil {
var cnt int64
cnt, err = DefaultHeffalump.WriteHell(sp.BufioWriter)
t.Logf("written: %d", cnt)
count += cnt
}
if !errors.Is(err, util.ErrLimitReached) {
t.Errorf("expected %v, got %v", util.ErrLimitReached, err)
} else {
t.Logf("err: %v", err)
}
t.Logf("count: %d", count)
t.Logf("rate: %f per second", sp.Rate())
}

File diff suppressed because one or more lines are too long

View File

@ -14,7 +14,7 @@ func init() {
if home, err = os.UserHomeDir(); err != nil {
panic(err)
}
defOpts["logger"]["directory"] = path.Join(home, ".local", "share", Title+"logs")
defOpts["logger"]["directory"] = path.Join(home, ".local", "share", Title, "logs")
prefConfigLocation = path.Join(home, ".config", Title)
}

View File

@ -22,15 +22,22 @@ func rc(s []string) string {
func process(in string) (s string) {
var v = strings.Split(config.Version, "")
maj := v[0]
min := v[2]
smin := v[4]
var maj, min, smin = "", "", ""
if len(config.Version) > 0 {
maj = v[0]
}
if len(config.Version) > 2 {
min = v[2]
}
if len(config.Version) > 4 {
smin = v[4]
}
defl8, _ := squish.UnpackStr(in)
sp := strings.Split(defl8, "|")
s = sp[0]
if smin == "" || len(config.Version) == 7 {
if smin == "" || len(config.Version) == 7 || config.Version == "dev" {
s = strings.ReplaceAll(s, "$1;40m.", "$1;40m")
if len(config.Version) == 7 {
if len(config.Version) == 7 || config.Version == "dev" {
s = strings.ReplaceAll(s, "$3;40m.", "$3;40m")
}
}
@ -46,7 +53,7 @@ func process(in string) (s string) {
for n := 1; n < 5; n++ {
s = cproc(s, fmt.Sprintf("%d", n))
}
if len(config.Version) == 7 {
if len(config.Version) == 7 || config.Version == "dev" {
maj = "[" + config.Version + "]"
min = ""
smin = ""

View File

@ -1,158 +0,0 @@
package util
import (
"bufio"
"errors"
"io"
"sync"
"sync/atomic"
"time"
)
var ErrLimitReached = errors.New("limit reached")
type Speedometer struct {
cap int64
speedLimit SpeedLimit
birth *time.Time
duration time.Duration
internal atomics
w io.Writer
BufioWriter *bufio.Writer
}
type atomics struct {
closed *atomic.Bool
count *int64
start *sync.Once
stop *sync.Once
}
func NewSpeedometer(w io.Writer) *Speedometer {
z := int64(0)
speedo := &Speedometer{
w: w,
cap: -1,
internal: atomics{
count: &z,
closed: new(atomic.Bool),
stop: new(sync.Once),
start: new(sync.Once),
},
}
speedo.internal.closed.Store(false)
speedo.BufioWriter = bufio.NewWriter(speedo)
return speedo
}
type SpeedLimit struct {
Bytes int
Per time.Duration
CheckEveryBytes int
Delay time.Duration
}
func NewLimitedSpeedometer(w io.Writer, speedLimit SpeedLimit) *Speedometer {
z := int64(0)
speedo := &Speedometer{
w: w,
cap: -1,
speedLimit: speedLimit,
internal: atomics{
count: &z,
closed: new(atomic.Bool),
stop: new(sync.Once),
start: new(sync.Once),
},
}
speedo.internal.closed.Store(false)
speedo.BufioWriter = bufio.NewWriterSize(speedo, speedLimit.CheckEveryBytes)
return speedo
}
func NewCappedSpeedometer(w io.Writer, cap int64) *Speedometer {
z := int64(0)
speedo := &Speedometer{
w: w,
cap: cap,
internal: atomics{
count: &z,
closed: new(atomic.Bool),
stop: new(sync.Once),
start: new(sync.Once),
},
}
speedo.internal.closed.Store(false)
speedo.BufioWriter = bufio.NewWriterSize(speedo, int(cap)/10)
return speedo
}
func (s *Speedometer) increment(inc int64) (int, error) {
if s.internal.closed.Load() {
return 0, io.ErrClosedPipe
}
var err error
if s.cap > 0 && s.Total()+inc > s.cap {
_ = s.Close()
err = ErrLimitReached
inc = s.cap - s.Total()
}
atomic.AddInt64(s.internal.count, inc)
return int(inc), err
}
func (s *Speedometer) Running() bool {
return !s.internal.closed.Load()
}
func (s *Speedometer) Total() int64 {
return atomic.LoadInt64(s.internal.count)
}
func (s *Speedometer) Reset() {
s.internal.count = new(int64)
s.internal.closed = new(atomic.Bool)
s.internal.start = new(sync.Once)
s.internal.stop = new(sync.Once)
s.BufioWriter = bufio.NewWriter(s)
s.internal.closed.Store(false)
}
func (s *Speedometer) Close() error {
s.internal.stop.Do(func() {
s.internal.closed.Store(true)
stopped := time.Now()
s.duration = stopped.Sub(*s.birth)
})
return nil
}
func (s *Speedometer) Rate() float64 {
if s.internal.closed.Load() {
return float64(s.Total()) / s.duration.Seconds()
}
return float64(s.Total()) / time.Since(*s.birth).Seconds()
}
func (s *Speedometer) Write(p []byte) (n int, err error) {
s.internal.start.Do(func() {
tn := time.Now()
s.birth = &tn
})
accepted, err := s.increment(int64(len(p)))
if err != nil {
wn, innerErr := s.w.Write(p[:accepted])
if innerErr != nil {
err = innerErr
}
if wn < accepted {
err = io.ErrShortWrite
}
return wn, err
}
return s.w.Write(p)
}
/*func BenchmarkHeffalump_WriteHell(b *testing.B) {
}*/

View File

@ -1,101 +0,0 @@
package util
import (
"bufio"
"errors"
"io"
"testing"
"time"
)
func writeStuff(target *bufio.Writer, count int) error {
write := func() error {
_, err := target.WriteString("a")
if err != nil {
return err
}
return nil
}
if count < 0 {
for {
if err := write(); err != nil {
return err
}
}
}
for i := 0; i < count; i++ {
if err := write(); err != nil {
return err
}
}
return nil
}
func Test_Speedometer(t *testing.T) {
type results struct {
total int64
written int
rate float64
err error
}
isIt := func(want, have results) {
if have.total != want.total {
t.Errorf("total: want %d, have %d", want.total, have.total)
}
if have.written != want.written {
t.Errorf("written: want %d, have %d", want.written, have.written)
}
if have.rate != want.rate {
t.Errorf("rate: want %f, have %f", want.rate, have.rate)
}
if have.err != want.err {
t.Errorf("wantErr: want %v, have %v", want.err, have.err)
}
}
sp := NewSpeedometer(io.Discard)
errChan := make(chan error)
go func() {
errChan <- writeStuff(sp.BufioWriter, -1)
}()
time.Sleep(1 * time.Second)
_ = sp.Close()
err := <-errChan
cnt, err := sp.Write([]byte("a"))
isIt(results{err: io.ErrClosedPipe, written: 0}, results{err: err, written: cnt})
sp.Reset()
cnt, err = sp.Write([]byte("a"))
isIt(results{err: nil, written: 1, total: 1}, results{err: err, written: cnt, total: sp.Total()})
cnt, err = sp.Write([]byte("aa"))
isIt(results{err: nil, written: 2, total: 3}, results{err: err, written: cnt, total: sp.Total()})
cnt, err = sp.Write([]byte("a"))
isIt(results{err: nil, written: 1, total: 4}, results{err: err, written: cnt, total: sp.Total()})
cnt, err = sp.Write([]byte("a"))
isIt(results{err: nil, written: 1, total: 5}, results{err: err, written: cnt, total: sp.Total()})
go func() {
errChan <- writeStuff(sp.BufioWriter, -1)
}()
var count = 0
for sp.Running() {
select {
case err = <-errChan:
if !errors.Is(err, io.ErrClosedPipe) {
t.Errorf("unexpected error: %v", err)
} else {
if count < 5 {
t.Errorf("too few iterations: %d", count)
}
t.Logf("final rate: %v per second", sp.Rate())
}
default:
if count > 5 {
_ = sp.Close()
}
t.Logf("rate: %v per second", sp.Rate())
time.Sleep(1 * time.Second)
count++
}
}
}