From 7f2d451ca4d7595ad882d7a91677e73ebc19b960 Mon Sep 17 00:00:00 2001 From: Bel LaPointe Date: Sun, 21 Feb 2021 12:39:15 -0600 Subject: [PATCH] move resolve into package --- bolt.go | 14 ++++--- cache.go | 9 +++-- db.go | 51 ------------------------- db_test.go | 83 +++-------------------------------------- files.go | 16 +++++--- leveldb.go | 11 +++--- map.go | 9 +++-- memcache.go | 5 ++- memcachecluster.go | 5 ++- minio.go | 9 +++-- mongo.go | 9 +++-- rclone.go | 11 +++--- redis.go | 11 +++--- resolve/resolve.go | 57 ++++++++++++++++++++++++++++ resolve/resolve_test.go | 80 +++++++++++++++++++++++++++++++++++++++ 15 files changed, 205 insertions(+), 175 deletions(-) create mode 100755 resolve/resolve.go create mode 100755 resolve/resolve_test.go diff --git a/bolt.go b/bolt.go index 461ec3f..27fb868 100755 --- a/bolt.go +++ b/bolt.go @@ -1,6 +1,10 @@ package storage -import "github.com/boltdb/bolt" +import ( + "local/storage/resolve" + + "github.com/boltdb/bolt" +) type Bolt struct { db *bolt.DB @@ -14,8 +18,8 @@ func NewBolt(path string) (*Bolt, error) { } func (b *Bolt) List(ns []string, limits ...string) ([]string, error) { - namespace := resolveNamespace(ns) - limits = resolveLimits(limits) + namespace := resolve.Namespace(ns) + limits = resolve.Limits(limits) found := []string{} err := b.db.View(func(tx *bolt.Tx) error { bucket := tx.Bucket([]byte(namespace)) @@ -33,7 +37,7 @@ func (b *Bolt) List(ns []string, limits ...string) ([]string, error) { } func (b *Bolt) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) var result []byte err := b.db.View(func(tx *bolt.Tx) error { bkt := tx.Bucket([]byte(namespace)) @@ -50,7 +54,7 @@ func (b *Bolt) Get(key string, ns ...string) ([]byte, error) { } func (b *Bolt) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) return b.db.Update(func(tx *bolt.Tx) error { bkt, err := tx.CreateBucketIfNotExists([]byte(namespace)) if err != nil { diff --git a/cache.go b/cache.go index 379e572..b8f2a0d 100755 --- a/cache.go +++ b/cache.go @@ -1,6 +1,7 @@ package storage import ( + "local/storage/resolve" "os" "path" "strings" @@ -27,8 +28,8 @@ func NewCache(path ...string) (*Cache, error) { } func (c *Cache) List(ns []string, limits ...string) ([]string, error) { - namespace := resolveNamespace(ns) - limits = resolveLimits(limits) + namespace := resolve.Namespace(ns) + limits = resolve.Limits(limits) limits[0] = path.Join(namespace, limits[0]) limits[1] = path.Join(namespace, limits[1]) m := c.db.Items() @@ -42,7 +43,7 @@ func (c *Cache) List(ns []string, limits ...string) ([]string, error) { } func (c *Cache) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) v, ok := c.db.Get(path.Join(namespace, key)) if !ok { return nil, ErrNotFound @@ -55,7 +56,7 @@ func (c *Cache) Get(key string, ns ...string) ([]byte, error) { } func (c *Cache) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) c.db.Set(path.Join(namespace, key), value, 0) return nil } diff --git a/db.go b/db.go index dc09b8f..546660a 100755 --- a/db.go +++ b/db.go @@ -3,8 +3,6 @@ package storage import ( "fmt" "io" - "strconv" - "strings" ) type DBStream interface { @@ -60,52 +58,3 @@ func New(key Type, params ...string) (db DB, err error) { } return } - -func resolveNamespace(ns []string) string { - namespace := DefaultNamespace - if len(ns) > 0 { - segments := []string{} - for i := range ns { - if ns[i] != "" { - segments = append(segments, ns[i]) - } - } - namespace = strings.Join(segments, ".") - } - return namespace -} - -func resolveLimits(input []string) []string { - return []string{ - resolveLimitsStart(input), - resolveLimitsStop(input), - resolveLimitsLimit(input), - resolveLimitsAscending(input), - } -} - -func resolveLimitsStart(input []string) string { - if len(input) > 0 { - return input[0] - } - return " " -} - -func resolveLimitsStop(input []string) string { - if len(input) > 1 { - return input[1] - } - return "}}}}}}" -} - -func resolveLimitsLimit(input []string) string { - if len(input) > 2 { - v, _ := strconv.Atoi(input[2]) - return strconv.Itoa(v) - } - return "0" -} - -func resolveLimitsAscending(input []string) string { - return strconv.FormatBool(len(input) < 4 || input[3] != "-") -} diff --git a/db_test.go b/db_test.go index 3e3cb8d..67126b0 100755 --- a/db_test.go +++ b/db_test.go @@ -3,6 +3,7 @@ package storage import ( "bytes" "io/ioutil" + "local/storage/resolve" "log" "net" "os" @@ -17,8 +18,8 @@ type mock struct { } func (mock *mock) List(ns []string, limits ...string) ([]string, error) { - namespace := resolveNamespace(ns) - limits = resolveLimits(limits) + namespace := resolve.Namespace(ns) + limits = resolve.Limits(limits) keys := []string{} for k := range mock.m { if k >= limits[0] && k <= limits[1] { @@ -29,7 +30,7 @@ func (mock *mock) List(ns []string, limits ...string) ([]string, error) { } func (mock *mock) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) v, ok := mock.m[path.Join(namespace, key)] if ok { return v, nil @@ -38,7 +39,7 @@ func (mock *mock) Get(key string, ns ...string) ([]byte, error) { } func (mock *mock) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) mock.m[path.Join(namespace, key)] = value return nil } @@ -313,77 +314,3 @@ func recoverDeferred(c Type, t *testing.T, wg *sync.WaitGroup) { } defer wg.Done() } - -func TestResolveLimitsStart(t *testing.T) { - cases := map[string]struct { - in string - out string - }{ - "explicit": {in: "no", out: "no"}, - } - - for name, c := range cases { - input := strings.Split(c.in, ",") - out := resolveLimitsStart(input) - if out != c.out { - t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) - } - } -} - -func TestResolveLimitsStop(t *testing.T) { - cases := map[string]struct { - in string - out string - }{ - "short arr": {in: "", out: "}}}}}}"}, - "explicit": {in: ",no", out: "no"}, - } - - for name, c := range cases { - input := strings.Split(c.in, ",") - out := resolveLimitsStop(input) - if out != c.out { - t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) - } - } -} - -func TestResolveLimitsLimit(t *testing.T) { - cases := map[string]struct { - in string - out string - }{ - "15": {in: ",,15", out: "15"}, - "0 set": {in: ",,0", out: "0"}, - "0 default": {in: ",,", out: "0"}, - } - - for name, c := range cases { - input := strings.Split(c.in, ",") - out := resolveLimitsLimit(input) - if out != c.out { - t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) - } - } -} - -func TestResolveLimitsAscending(t *testing.T) { - cases := map[string]struct { - in string - out string - }{ - "desc": {in: "a,b,c,-", out: "false"}, - "asc": {in: "a,b,c,+", out: "true"}, - "default asc prev": {in: "a,b,c,", out: "true"}, - "default asc empty": {in: ",,,", out: "true"}, - } - - for name, c := range cases { - input := strings.Split(c.in, ",") - out := resolveLimitsAscending(input) - if out != c.out { - t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) - } - } -} diff --git a/files.go b/files.go index c71abf0..fe2136d 100755 --- a/files.go +++ b/files.go @@ -4,6 +4,8 @@ import ( "bytes" "io" "io/ioutil" + "local/storage/resolve" + "log" "os" "path" "path/filepath" @@ -29,7 +31,7 @@ func NewFiles(root string) (*Files, error) { } func (b *Files) List(ns []string, limits ...string) ([]string, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) files := make([]string, 0) err := filepath.Walk(b.root, func(p string, info os.FileInfo, err error) error { if err != nil { @@ -46,7 +48,7 @@ func (b *Files) List(ns []string, limits ...string) ([]string, error) { }) return files, err /* - limits = resolveLimits(limits) + limits = resolve.Limits(limits) */ } @@ -59,12 +61,13 @@ func (b *Files) Get(key string, ns ...string) ([]byte, error) { } func (b *Files) GetStream(key string, ns ...string) (io.Reader, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) path := path.Join(b.root, namespace, key) return os.Open(path) } func (b *Files) Set(key string, value []byte, ns ...string) error { + log.Println("files.Set", ns, key, "to", len(value), value == nil) r := bytes.NewReader(value) if value == nil { r = nil @@ -73,10 +76,12 @@ func (b *Files) Set(key string, value []byte, ns ...string) error { } func (b *Files) SetStream(key string, r io.Reader, ns ...string) error { - namespace := resolveNamespace(ns) + log.Println("files.SetStream", ns, key, "to", r, r == nil) + namespace := resolve.Namespace(ns) dir := path.Join(b.root, namespace) + path := path.Join(dir, key) if r == nil { - err := os.Remove(path.Join(dir, key)) + err := os.Remove(path) if os.IsNotExist(err) { err = nil } @@ -85,7 +90,6 @@ func (b *Files) SetStream(key string, r io.Reader, ns ...string) error { if err := os.MkdirAll(dir, os.ModePerm); err != nil { return err } - path := path.Join(dir, key) f, err := os.Create(path) if err != nil { return err diff --git a/leveldb.go b/leveldb.go index bb6843a..d077301 100755 --- a/leveldb.go +++ b/leveldb.go @@ -1,6 +1,7 @@ package storage import ( + "local/storage/resolve" "path" "strconv" "strings" @@ -39,7 +40,7 @@ func NewLevelDB(path string) (*LevelDB, error) { } func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) snapshot, err := ldb.db.GetSnapshot() if err != nil { return nil, err @@ -57,7 +58,7 @@ func (ldb *LevelDB) Get(key string, ns ...string) ([]byte, error) { } func (ldb *LevelDB) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) key = path.Join(namespace, key) batch := &leveldb.Batch{} if value != nil { @@ -73,8 +74,8 @@ func (ldb *LevelDB) Close() error { } func (ldb *LevelDB) List(ns []string, limits ...string) ([]string, error) { - namespace := path.Join(resolveNamespace(ns)) - limits = resolveLimits(limits) + namespace := path.Join(resolve.Namespace(ns)) + limits = resolve.Limits(limits) it, next := ldb.getIterator(namespace, limits) defer it.Release() keys := ldb.useIterator(it, next, namespace, limits) @@ -99,7 +100,7 @@ func (ldb *LevelDB) getIterator(namespace string, limits []string) (iterator.Ite } func (ldb *LevelDB) useIterator(it iterator.Iterator, next func() bool, namespace string, limits []string) []string { - limits = resolveLimits(limits) + limits = resolve.Limits(limits) n, _ := strconv.Atoi(limits[2]) m := 0 diff --git a/map.go b/map.go index cd25eb6..c45807f 100755 --- a/map.go +++ b/map.go @@ -2,6 +2,7 @@ package storage import ( "fmt" + "local/storage/resolve" "sync" ) @@ -40,8 +41,8 @@ func (m *Map) Close() error { func (m *Map) List(ns []string, limits ...string) ([]string, error) { m.lock.RLock() defer m.lock.RUnlock() - namespace := resolveNamespace(ns) - limits = resolveLimits(limits) + namespace := resolve.Namespace(ns) + limits = resolve.Limits(limits) keys := []string{} if _, ok := m.m[namespace]; !ok { @@ -59,7 +60,7 @@ func (m *Map) List(ns []string, limits ...string) ([]string, error) { func (m *Map) Get(key string, ns ...string) ([]byte, error) { m.lock.RLock() defer m.lock.RUnlock() - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) if _, ok := m.m[namespace]; !ok { return nil, ErrNotFound } @@ -72,7 +73,7 @@ func (m *Map) Get(key string, ns ...string) ([]byte, error) { func (m *Map) Set(key string, value []byte, ns ...string) error { m.lock.Lock() defer m.lock.Unlock() - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) if value == nil { if _, ok := m.m[namespace]; !ok { return nil diff --git a/memcache.go b/memcache.go index 18542ca..bed1653 100755 --- a/memcache.go +++ b/memcache.go @@ -2,6 +2,7 @@ package storage import ( "errors" + "local/storage/resolve" "net" "path" @@ -53,7 +54,7 @@ func (mc *Memcache) List(ns []string, limits ...string) ([]string, error) { } func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) v, err := mc.db.Get(path.Join(namespace, key)) if err != nil { return nil, err @@ -65,7 +66,7 @@ func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) { } func (mc *Memcache) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) return mc.db.Set(&memcache.Item{ Key: path.Join(namespace, key), Value: value, diff --git a/memcachecluster.go b/memcachecluster.go index ca21b59..bf775dc 100755 --- a/memcachecluster.go +++ b/memcachecluster.go @@ -2,6 +2,7 @@ package storage import ( "errors" + "local/storage/resolve" "net" "path" @@ -75,13 +76,13 @@ func (mc *MemcacheCluster) List(ns []string, limits ...string) ([]string, error) } func (mc *MemcacheCluster) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) v, err := mc.db.Get(path.Join(namespace, key)) return v.Value, err } func (mc *MemcacheCluster) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) return mc.db.Set(&memcache.Item{ Key: path.Join(namespace, key), Value: value, diff --git a/minio.go b/minio.go index fb15bcc..f46270e 100755 --- a/minio.go +++ b/minio.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "io/ioutil" + "local/storage/resolve" "net/url" "sort" "strings" @@ -27,8 +28,8 @@ func NewMinio(addr, user, pass string) (*Minio, error) { } func (m *Minio) List(ns []string, limits ...string) ([]string, error) { - namespace := resolveNamespace(ns) - limits = resolveLimits(limits) + namespace := resolve.Namespace(ns) + limits = resolve.Limits(limits) done := make(chan struct{}) defer close(done) keys := []string{} @@ -51,7 +52,7 @@ func (m *Minio) List(ns []string, limits ...string) ([]string, error) { } func (m *Minio) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) obj, err := m.db.GetObject(namespace, key, minio.GetObjectOptions{}) if err == nil { var stat minio.ObjectInfo @@ -68,7 +69,7 @@ func (m *Minio) Get(key string, ns ...string) ([]byte, error) { } func (m *Minio) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) if ok, err := m.db.BucketExists(namespace); err != nil { return err } else if !ok { diff --git a/mongo.go b/mongo.go index 9199097..f2039b9 100755 --- a/mongo.go +++ b/mongo.go @@ -3,6 +3,7 @@ package storage import ( "context" "errors" + "local/storage/resolve" "strings" "time" @@ -55,8 +56,8 @@ func NewMongo(addr string, auth ...string) (*Mongo, error) { } func (mg *Mongo) List(ns []string, limits ...string) ([]string, error) { - namespace := resolveNamespace(ns) - limits = resolveLimits(limits) + namespace := resolve.Namespace(ns) + limits = resolve.Limits(limits) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() collection := mg.db.Database(DefaultNamespace).Collection(namespace) @@ -88,7 +89,7 @@ func (mg *Mongo) List(ns []string, limits ...string) ([]string, error) { } func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() collection := mg.db.Database(DefaultNamespace).Collection(namespace) @@ -118,7 +119,7 @@ func (mg *Mongo) Get(key string, ns ...string) ([]byte, error) { } func (mg *Mongo) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(ns) + namespace := resolve.Namespace(ns) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) defer cancel() collection := mg.db.Database(DefaultNamespace).Collection(namespace) diff --git a/rclone.go b/rclone.go index 4bf6c67..3442e7a 100755 --- a/rclone.go +++ b/rclone.go @@ -4,6 +4,7 @@ import ( "bytes" "io" "io/ioutil" + "local/storage/resolve" "os" "path" "time" @@ -46,7 +47,7 @@ func (rc *RClone) Get(key string, ns ...string) ([]byte, error) { func (rc *RClone) GetStream(key string, ns ...string) (io.Reader, error) { namespace := rc.ns if len(ns) > 0 { - namespace = path.Join(rc.ns, resolveNamespace(ns)) + namespace = path.Join(rc.ns, resolve.Namespace(ns)) } key = path.Join(namespace, key) @@ -71,7 +72,7 @@ func (rc *RClone) Set(key string, value []byte, ns ...string) error { func (rc *RClone) SetStream(key string, r io.Reader, ns ...string) error { namespace := rc.ns if len(ns) > 0 { - namespace = path.Join(rc.ns, resolveNamespace(ns)) + namespace = path.Join(rc.ns, resolve.Namespace(ns)) } key = path.Join(namespace, key) @@ -87,7 +88,7 @@ func (rc *RClone) SetStream(key string, r io.Reader, ns ...string) error { func (rc *RClone) Del(key string, ns ...string) error { namespace := rc.ns if len(ns) > 0 { - namespace = path.Join(rc.ns, resolveNamespace(ns)) + namespace = path.Join(rc.ns, resolve.Namespace(ns)) } key = path.Join(namespace, key) @@ -112,9 +113,9 @@ func (rc *RClone) Close() error { func (rc *RClone) List(ns []string, limits ...string) ([]string, error) { namespace := rc.ns if len(ns) > 0 { - namespace = path.Join(rc.ns, resolveNamespace(ns)) + namespace = path.Join(rc.ns, resolve.Namespace(ns)) } - limits = resolveLimits(limits) + limits = resolve.Limits(limits) f, err := fs.NewFs(namespace) if err != nil { diff --git a/redis.go b/redis.go index 96ab331..0c02298 100755 --- a/redis.go +++ b/redis.go @@ -3,6 +3,7 @@ package storage import ( "errors" "fmt" + "local/storage/resolve" "time" "github.com/gomodule/redigo/redis" @@ -33,9 +34,9 @@ func (m *Redis) Close() error { } func (m *Redis) List(ns []string, limits ...string) ([]string, error) { - limits = resolveLimits(limits) - limits[0] = resolveNamespace(append(ns, limits[0])) - limits[1] = resolveNamespace(append(ns, limits[1])) + limits = resolve.Limits(limits) + limits[0] = resolve.Namespace(append(ns, limits[0])) + limits[1] = resolve.Namespace(append(ns, limits[1])) resp, err := m.client.Do("KEYS", "*") if err != nil { @@ -65,7 +66,7 @@ func (m *Redis) List(ns []string, limits ...string) ([]string, error) { } func (m *Redis) Get(key string, ns ...string) ([]byte, error) { - key = resolveNamespace(append(ns, key)) + key = resolve.Namespace(append(ns, key)) resp, err := m.client.Do("GET", key) if err != nil { return nil, err @@ -81,7 +82,7 @@ func (m *Redis) Get(key string, ns ...string) ([]byte, error) { } func (m *Redis) Set(key string, value []byte, ns ...string) error { - namespace := resolveNamespace(append(ns, key)) + namespace := resolve.Namespace(append(ns, key)) _, err := m.client.Do("SET", namespace, value) return err } diff --git a/resolve/resolve.go b/resolve/resolve.go new file mode 100755 index 0000000..488e283 --- /dev/null +++ b/resolve/resolve.go @@ -0,0 +1,57 @@ +package resolve + +import ( + "strconv" + "strings" +) + +var DefaultNamespace = "namespace" + +func Namespace(ns []string) string { + namespace := DefaultNamespace + if len(ns) > 0 { + segments := []string{} + for i := range ns { + if ns[i] != "" { + segments = append(segments, ns[i]) + } + } + namespace = strings.Join(segments, ".") + } + return namespace +} + +func Limits(input []string) []string { + return []string{ + LimitsStart(input), + LimitsStop(input), + LimitsLimit(input), + LimitsAscending(input), + } +} + +func LimitsStart(input []string) string { + if len(input) > 0 { + return input[0] + } + return " " +} + +func LimitsStop(input []string) string { + if len(input) > 1 { + return input[1] + } + return "}}}}}}" +} + +func LimitsLimit(input []string) string { + if len(input) > 2 { + v, _ := strconv.Atoi(input[2]) + return strconv.Itoa(v) + } + return "0" +} + +func LimitsAscending(input []string) string { + return strconv.FormatBool(len(input) < 4 || input[3] != "-") +} diff --git a/resolve/resolve_test.go b/resolve/resolve_test.go new file mode 100755 index 0000000..d120a5f --- /dev/null +++ b/resolve/resolve_test.go @@ -0,0 +1,80 @@ +package resolve + +import ( + "strings" + "testing" +) + +func TestResolveLimitsStart(t *testing.T) { + cases := map[string]struct { + in string + out string + }{ + "explicit": {in: "no", out: "no"}, + } + + for name, c := range cases { + input := strings.Split(c.in, ",") + out := LimitsStart(input) + if out != c.out { + t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) + } + } +} + +func TestResolveLimitsStop(t *testing.T) { + cases := map[string]struct { + in string + out string + }{ + "short arr": {in: "", out: "}}}}}}"}, + "explicit": {in: ",no", out: "no"}, + } + + for name, c := range cases { + input := strings.Split(c.in, ",") + out := LimitsStop(input) + if out != c.out { + t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) + } + } +} + +func TestResolveLimitsLimit(t *testing.T) { + cases := map[string]struct { + in string + out string + }{ + "15": {in: ",,15", out: "15"}, + "0 set": {in: ",,0", out: "0"}, + "0 default": {in: ",,", out: "0"}, + } + + for name, c := range cases { + input := strings.Split(c.in, ",") + out := LimitsLimit(input) + if out != c.out { + t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) + } + } +} + +func TestResolveLimitsAscending(t *testing.T) { + cases := map[string]struct { + in string + out string + }{ + "desc": {in: "a,b,c,-", out: "false"}, + "asc": {in: "a,b,c,+", out: "true"}, + "default asc prev": {in: "a,b,c,", out: "true"}, + "default asc empty": {in: ",,,", out: "true"}, + } + + for name, c := range cases { + input := strings.Split(c.in, ",") + out := LimitsAscending(input) + if out != c.out { + t.Errorf("%v: got %v, want %v from %v", name, out, c.out, c.in) + } + } +}