mirror of
https://github.com/ClusterCockpit/cc-units.git
synced 2024-11-10 02:07:25 +01:00
Add new prefixes, add some more interface functions
This commit is contained in:
parent
8c6fa4c4bc
commit
a6e40789e4
31
README.md
31
README.md
@ -5,8 +5,10 @@ When working with metrics, the problem comes up that they may use different unit
|
|||||||
In order to enable unit comparison and conversion, the ccUnits package provides some helpers:
|
In order to enable unit comparison and conversion, the ccUnits package provides some helpers:
|
||||||
There are basically two important functions:
|
There are basically two important functions:
|
||||||
```go
|
```go
|
||||||
NewUnit(unit string) Unit
|
NewUnit(unit string) Unit // create a new unit from some string like 'GHz', 'Mbyte' or 'kevents/s'
|
||||||
GetUnitPrefixFactor(in Unit, out Unit) (func(value float64) float64, error) // Get conversion function for the value
|
func GetUnitUnitFactor(in Unit, out Unit) (func(value float64) float64, error) // Get conversion function between two units
|
||||||
|
func GetPrefixFactor(in Prefix, out Prefix) func(value float64) float64 // Get conversion function between two prefixes
|
||||||
|
func GetUnitPrefixFactor(in Unit, out Prefix) (func(value float64) float64, Unit) // Get conversion function for prefix changes and the new unit for further use
|
||||||
|
|
||||||
type Unit interface {
|
type Unit interface {
|
||||||
Valid() bool
|
Valid() bool
|
||||||
@ -26,14 +28,35 @@ v := NewUnit("foo")
|
|||||||
fmt.Println(v.Valid()) // false
|
fmt.Println(v.Valid()) // false
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have two units and need the conversion function:
|
If you have two units or other components and need the conversion function:
|
||||||
```go
|
```go
|
||||||
|
// Get conversion functions for 'kB' to 'MBytes'
|
||||||
u1 := NewUnit("kB")
|
u1 := NewUnit("kB")
|
||||||
u2 := NewUnit("MBytes")
|
u2 := NewUnit("MBytes")
|
||||||
convFunc, err := GetUnitPrefixFactor(u1, u2) // Returns an error if the units have different measures
|
convFunc, err := GetUnitUnitFactor(u1, u2) // Returns an error if the units have different measures
|
||||||
if err == nil {
|
if err == nil {
|
||||||
v2 := convFunc(v1)
|
v2 := convFunc(v1)
|
||||||
|
fmt.Printf("%f %s\n", v2, u2.Short())
|
||||||
}
|
}
|
||||||
|
// Get conversion function for 'kB' -> 'G' prefix.
|
||||||
|
// Returns the function and the new unit 'GBytes'
|
||||||
|
p1 := NewPrefix("G")
|
||||||
|
convFunc, u_p1 := GetUnitPrefixFactor(u1, p1)
|
||||||
|
// or
|
||||||
|
// convFunc, u_p1 := GetUnitPrefixStringFactor(u1, "G")
|
||||||
|
if convFunc != nil {
|
||||||
|
v2 := convFunc(v1)
|
||||||
|
fmt.Printf("%f %s\n", v2, u_p1.Short())
|
||||||
|
}
|
||||||
|
// Get conversion function for two prefixes: 'G' -> 'T'
|
||||||
|
p2 := NewPrefix("T")
|
||||||
|
convFunc = GetPrefixPrefixFactor(p1, p2)
|
||||||
|
if convFunc != nil {
|
||||||
|
v2 := convFunc(v1)
|
||||||
|
fmt.Printf("%f %s -> %f %s\n", v1, p1.Prefix(), v2, p2.Prefix())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
(In the ClusterCockpit ecosystem the separation between values and units if useful since they are commonly not stored as a single entity but the value is a field in the CCMetric while unit is a tag or a meta information).
|
(In the ClusterCockpit ecosystem the separation between values and units if useful since they are commonly not stored as a single entity but the value is a field in the CCMetric while unit is a tag or a meta information).
|
||||||
|
@ -5,7 +5,7 @@ import "regexp"
|
|||||||
type Measure int
|
type Measure int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
None Measure = iota
|
InvalidMeasure Measure = iota
|
||||||
Bytes
|
Bytes
|
||||||
Flops
|
Flops
|
||||||
Percentage
|
Percentage
|
||||||
@ -25,7 +25,7 @@ const (
|
|||||||
func (m *Measure) String() string {
|
func (m *Measure) String() string {
|
||||||
switch *m {
|
switch *m {
|
||||||
case Bytes:
|
case Bytes:
|
||||||
return "Bytes"
|
return "byte"
|
||||||
case Flops:
|
case Flops:
|
||||||
return "Flops"
|
return "Flops"
|
||||||
case Percentage:
|
case Percentage:
|
||||||
@ -52,6 +52,8 @@ func (m *Measure) String() string {
|
|||||||
return "Packets"
|
return "Packets"
|
||||||
case Events:
|
case Events:
|
||||||
return "Events"
|
return "Events"
|
||||||
|
case InvalidMeasure:
|
||||||
|
return "Invalid"
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
@ -60,7 +62,7 @@ func (m *Measure) String() string {
|
|||||||
func (m *Measure) Short() string {
|
func (m *Measure) Short() string {
|
||||||
switch *m {
|
switch *m {
|
||||||
case Bytes:
|
case Bytes:
|
||||||
return "Bytes"
|
return "B"
|
||||||
case Flops:
|
case Flops:
|
||||||
return "Flops"
|
return "Flops"
|
||||||
case Percentage:
|
case Percentage:
|
||||||
@ -87,6 +89,8 @@ func (m *Measure) Short() string {
|
|||||||
return "packets"
|
return "packets"
|
||||||
case Events:
|
case Events:
|
||||||
return "events"
|
return "events"
|
||||||
|
case InvalidMeasure:
|
||||||
|
return "Invalid"
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
@ -180,5 +184,5 @@ func NewMeasure(unit string) Measure {
|
|||||||
if match != nil {
|
if match != nil {
|
||||||
return Events
|
return Events
|
||||||
}
|
}
|
||||||
return None
|
return InvalidMeasure
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,10 @@ import "regexp"
|
|||||||
type Prefix float64
|
type Prefix float64
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Base Prefix = 1
|
InvalidPrefix Prefix = iota
|
||||||
|
Base = 1
|
||||||
|
Yotta = 1e24
|
||||||
|
Zetta = 1e21
|
||||||
Exa = 1e18
|
Exa = 1e18
|
||||||
Peta = 1e15
|
Peta = 1e15
|
||||||
Tera = 1e12
|
Tera = 1e12
|
||||||
@ -19,6 +22,10 @@ const (
|
|||||||
Mebi = 1024 * 1024
|
Mebi = 1024 * 1024
|
||||||
Gibi = 1024 * 1024 * 1024
|
Gibi = 1024 * 1024 * 1024
|
||||||
Tebi = 1024 * 1024 * 1024 * 1024
|
Tebi = 1024 * 1024 * 1024 * 1024
|
||||||
|
Pebi = 1024 * 1024 * 1024 * 1024 * 1024
|
||||||
|
Exbi = 1024 * 1024 * 1024 * 1024 * 1024 * 1024
|
||||||
|
Zebi = 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024
|
||||||
|
Yobi = 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024 * 1024
|
||||||
)
|
)
|
||||||
const prefixRegexStr = `^([kKmMgGtTpP]?[i]?)(.*)`
|
const prefixRegexStr = `^([kKmMgGtTpP]?[i]?)(.*)`
|
||||||
|
|
||||||
@ -26,6 +33,8 @@ var prefixRegex = regexp.MustCompile(prefixRegexStr)
|
|||||||
|
|
||||||
func (s *Prefix) String() string {
|
func (s *Prefix) String() string {
|
||||||
switch *s {
|
switch *s {
|
||||||
|
case InvalidPrefix:
|
||||||
|
return "Inval"
|
||||||
case Base:
|
case Base:
|
||||||
return ""
|
return ""
|
||||||
case Kilo:
|
case Kilo:
|
||||||
@ -40,6 +49,10 @@ func (s *Prefix) String() string {
|
|||||||
return "Peta"
|
return "Peta"
|
||||||
case Exa:
|
case Exa:
|
||||||
return "Exa"
|
return "Exa"
|
||||||
|
case Zetta:
|
||||||
|
return "Zetta"
|
||||||
|
case Yotta:
|
||||||
|
return "Yotta"
|
||||||
case Milli:
|
case Milli:
|
||||||
return "Milli"
|
return "Milli"
|
||||||
case Micro:
|
case Micro:
|
||||||
@ -61,6 +74,8 @@ func (s *Prefix) String() string {
|
|||||||
|
|
||||||
func (s *Prefix) Prefix() string {
|
func (s *Prefix) Prefix() string {
|
||||||
switch *s {
|
switch *s {
|
||||||
|
case InvalidPrefix:
|
||||||
|
return "<inval>"
|
||||||
case Base:
|
case Base:
|
||||||
return ""
|
return ""
|
||||||
case Kilo:
|
case Kilo:
|
||||||
@ -75,6 +90,10 @@ func (s *Prefix) Prefix() string {
|
|||||||
return "P"
|
return "P"
|
||||||
case Exa:
|
case Exa:
|
||||||
return "E"
|
return "E"
|
||||||
|
case Zetta:
|
||||||
|
return "Z"
|
||||||
|
case Yotta:
|
||||||
|
return "Y"
|
||||||
case Milli:
|
case Milli:
|
||||||
return "m"
|
return "m"
|
||||||
case Micro:
|
case Micro:
|
||||||
@ -120,6 +139,14 @@ func NewPrefix(prefix string) Prefix {
|
|||||||
return Exa
|
return Exa
|
||||||
case "E":
|
case "E":
|
||||||
return Exa
|
return Exa
|
||||||
|
case "z":
|
||||||
|
return Zetta
|
||||||
|
case "Z":
|
||||||
|
return Zetta
|
||||||
|
case "y":
|
||||||
|
return Yotta
|
||||||
|
case "Y":
|
||||||
|
return Yotta
|
||||||
case "u":
|
case "u":
|
||||||
return Micro
|
return Micro
|
||||||
case "n":
|
case "n":
|
||||||
@ -139,6 +166,6 @@ func NewPrefix(prefix string) Prefix {
|
|||||||
case "":
|
case "":
|
||||||
return Base
|
return Base
|
||||||
default:
|
default:
|
||||||
return Base
|
return InvalidPrefix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
61
ccUnits.go
61
ccUnits.go
@ -19,14 +19,17 @@ type Unit interface {
|
|||||||
getPrefix() Prefix
|
getPrefix() Prefix
|
||||||
getMeasure() Measure
|
getMeasure() Measure
|
||||||
getDivMeasure() Measure
|
getDivMeasure() Measure
|
||||||
|
setPrefix(p Prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var INVALID_UNIT = NewUnit("foobar")
|
||||||
|
|
||||||
func (u *unit) Valid() bool {
|
func (u *unit) Valid() bool {
|
||||||
return u.measure != None
|
return u.measure != InvalidMeasure
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *unit) String() string {
|
func (u *unit) String() string {
|
||||||
if u.divMeasure != None {
|
if u.divMeasure != InvalidMeasure {
|
||||||
return fmt.Sprintf("%s%s/%s", u.prefix.String(), u.measure.String(), u.divMeasure.String())
|
return fmt.Sprintf("%s%s/%s", u.prefix.String(), u.measure.String(), u.divMeasure.String())
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("%s%s", u.prefix.String(), u.measure.String())
|
return fmt.Sprintf("%s%s", u.prefix.String(), u.measure.String())
|
||||||
@ -34,7 +37,7 @@ func (u *unit) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (u *unit) Short() string {
|
func (u *unit) Short() string {
|
||||||
if u.divMeasure != None {
|
if u.divMeasure != InvalidMeasure {
|
||||||
return fmt.Sprintf("%s%s/%s", u.prefix.Prefix(), u.measure.Short(), u.divMeasure.Short())
|
return fmt.Sprintf("%s%s/%s", u.prefix.Prefix(), u.measure.Short(), u.divMeasure.Short())
|
||||||
} else {
|
} else {
|
||||||
return fmt.Sprintf("%s%s", u.prefix.Prefix(), u.measure.Short())
|
return fmt.Sprintf("%s%s", u.prefix.Prefix(), u.measure.Short())
|
||||||
@ -49,6 +52,10 @@ func (u *unit) getPrefix() Prefix {
|
|||||||
return u.prefix
|
return u.prefix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *unit) setPrefix(p Prefix) {
|
||||||
|
u.prefix = p
|
||||||
|
}
|
||||||
|
|
||||||
func (u *unit) getMeasure() Measure {
|
func (u *unit) getMeasure() Measure {
|
||||||
return u.measure
|
return u.measure
|
||||||
}
|
}
|
||||||
@ -57,7 +64,7 @@ func (u *unit) getDivMeasure() Measure {
|
|||||||
return u.divMeasure
|
return u.divMeasure
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPrefixFactor(in Prefix, out Prefix) func(value float64) float64 {
|
func GetPrefixPrefixFactor(in Prefix, out Prefix) func(value float64) float64 {
|
||||||
var factor = 1.0
|
var factor = 1.0
|
||||||
var in_prefix = float64(in)
|
var in_prefix = float64(in)
|
||||||
var out_prefix = float64(out)
|
var out_prefix = float64(out)
|
||||||
@ -65,7 +72,33 @@ func GetPrefixFactor(in Prefix, out Prefix) func(value float64) float64 {
|
|||||||
return func(value float64) float64 { return factor }
|
return func(value float64) float64 { return factor }
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetUnitPrefixFactor(in Unit, out Unit) (func(value float64) float64, error) {
|
func GetPrefixStringPrefixStringFactor(in string, out string) func(value float64) float64 {
|
||||||
|
var i Prefix = NewPrefix(in)
|
||||||
|
var o Prefix = NewPrefix(out)
|
||||||
|
return GetPrefixPrefixFactor(i, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUnitPrefixFactor(in Unit, out Prefix) (func(value float64) float64, Unit) {
|
||||||
|
outUnit := NewUnit(in.Short())
|
||||||
|
if outUnit.Valid() {
|
||||||
|
outUnit.setPrefix(out)
|
||||||
|
conv := GetPrefixPrefixFactor(in.getPrefix(), out)
|
||||||
|
return conv, outUnit
|
||||||
|
}
|
||||||
|
return nil, INVALID_UNIT
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUnitPrefixStringFactor(in Unit, out string) (func(value float64) float64, Unit) {
|
||||||
|
var o Prefix = NewPrefix(out)
|
||||||
|
return GetUnitPrefixFactor(in, o)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUnitStringPrefixStringFactor(in string, out string) (func(value float64) float64, Unit) {
|
||||||
|
var i = NewUnit(in)
|
||||||
|
return GetUnitPrefixStringFactor(i, out)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetUnitUnitFactor(in Unit, out Unit) (func(value float64) float64, error) {
|
||||||
if in.getMeasure() == TemperatureC && out.getMeasure() == TemperatureF {
|
if in.getMeasure() == TemperatureC && out.getMeasure() == TemperatureF {
|
||||||
return func(value float64) float64 { return (value * 1.8) + 32 }, nil
|
return func(value float64) float64 { return (value * 1.8) + 32 }, nil
|
||||||
} else if in.getMeasure() == TemperatureF && out.getMeasure() == TemperatureC {
|
} else if in.getMeasure() == TemperatureF && out.getMeasure() == TemperatureC {
|
||||||
@ -73,14 +106,14 @@ func GetUnitPrefixFactor(in Unit, out Unit) (func(value float64) float64, error)
|
|||||||
} else if in.getMeasure() != out.getMeasure() || in.getDivMeasure() != out.getDivMeasure() {
|
} else if in.getMeasure() != out.getMeasure() || in.getDivMeasure() != out.getDivMeasure() {
|
||||||
return func(value float64) float64 { return 1.0 }, fmt.Errorf("invalid measures in in and out Unit")
|
return func(value float64) float64 { return 1.0 }, fmt.Errorf("invalid measures in in and out Unit")
|
||||||
}
|
}
|
||||||
return GetPrefixFactor(in.getPrefix(), out.getPrefix()), nil
|
return GetPrefixPrefixFactor(in.getPrefix(), out.getPrefix()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewUnit(unitStr string) Unit {
|
func NewUnit(unitStr string) Unit {
|
||||||
u := &unit{
|
u := &unit{
|
||||||
prefix: Base,
|
prefix: InvalidPrefix,
|
||||||
measure: None,
|
measure: InvalidMeasure,
|
||||||
divMeasure: None,
|
divMeasure: InvalidMeasure,
|
||||||
}
|
}
|
||||||
matches := prefixRegex.FindStringSubmatch(unitStr)
|
matches := prefixRegex.FindStringSubmatch(unitStr)
|
||||||
if len(matches) > 2 {
|
if len(matches) > 2 {
|
||||||
@ -90,17 +123,17 @@ func NewUnit(unitStr string) Unit {
|
|||||||
// Special case for prefix 'p' or 'P' (Peta) and measures starting with 'p' or 'P'
|
// Special case for prefix 'p' or 'P' (Peta) and measures starting with 'p' or 'P'
|
||||||
// like 'packets' or 'percent'. Same for 'e' or 'E' (Exa) for measures starting with
|
// like 'packets' or 'percent'. Same for 'e' or 'E' (Exa) for measures starting with
|
||||||
// 'e' or 'E' like 'events'
|
// 'e' or 'E' like 'events'
|
||||||
if m == None {
|
if m == InvalidMeasure {
|
||||||
switch pre {
|
switch pre {
|
||||||
case Peta, Exa:
|
case Peta, Exa:
|
||||||
t := NewMeasure(matches[1] + measures[0])
|
t := NewMeasure(matches[1] + measures[0])
|
||||||
if t != None {
|
if t != InvalidMeasure {
|
||||||
m = t
|
m = t
|
||||||
pre = Base
|
pre = Base
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
div := None
|
div := InvalidMeasure
|
||||||
if len(measures) > 1 {
|
if len(measures) > 1 {
|
||||||
div = NewMeasure(measures[1])
|
div = NewMeasure(measures[1])
|
||||||
}
|
}
|
||||||
@ -115,9 +148,13 @@ func NewUnit(unitStr string) Unit {
|
|||||||
case Percentage:
|
case Percentage:
|
||||||
pre = Base
|
pre = Base
|
||||||
}
|
}
|
||||||
|
if pre != InvalidPrefix && m != InvalidMeasure {
|
||||||
u.prefix = pre
|
u.prefix = pre
|
||||||
u.measure = m
|
u.measure = m
|
||||||
|
if div != InvalidMeasure {
|
||||||
u.divMeasure = div
|
u.divMeasure = div
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ func TestUnitsExact(t *testing.T) {
|
|||||||
{"GB", NewUnit("GBytes")},
|
{"GB", NewUnit("GBytes")},
|
||||||
{"Hz", NewUnit("Hertz")},
|
{"Hz", NewUnit("Hertz")},
|
||||||
{"MHz", NewUnit("MHertz")},
|
{"MHz", NewUnit("MHertz")},
|
||||||
{"GHertz", NewUnit("GHertz")},
|
{"GHz", NewUnit("GHertz")},
|
||||||
{"pkts", NewUnit("Packets")},
|
{"pkts", NewUnit("Packets")},
|
||||||
{"packets", NewUnit("Packets")},
|
{"packets", NewUnit("Packets")},
|
||||||
{"packet", NewUnit("Packets")},
|
{"packet", NewUnit("Packets")},
|
||||||
@ -44,7 +44,7 @@ func TestUnitsExact(t *testing.T) {
|
|||||||
{"event", NewUnit("events")},
|
{"event", NewUnit("events")},
|
||||||
{"EveNts", NewUnit("events")},
|
{"EveNts", NewUnit("events")},
|
||||||
{"reqs", NewUnit("requests")},
|
{"reqs", NewUnit("requests")},
|
||||||
{"requests", NewUnit("requests")},
|
{"reQuEsTs", NewUnit("requests")},
|
||||||
{"Requests", NewUnit("requests")},
|
{"Requests", NewUnit("requests")},
|
||||||
{"cyc", NewUnit("cycles")},
|
{"cyc", NewUnit("cycles")},
|
||||||
{"cy", NewUnit("cycles")},
|
{"cy", NewUnit("cycles")},
|
||||||
@ -79,7 +79,7 @@ func TestUnitsExact(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnitsDifferentPrefix(t *testing.T) {
|
func TestUnitUnitConversion(t *testing.T) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
in string
|
in string
|
||||||
want Unit
|
want Unit
|
||||||
@ -97,7 +97,7 @@ func TestUnitsDifferentPrefix(t *testing.T) {
|
|||||||
}
|
}
|
||||||
compareUnitWithPrefix := func(in, out Unit, factor float64) bool {
|
compareUnitWithPrefix := func(in, out Unit, factor float64) bool {
|
||||||
if in.getMeasure() == out.getMeasure() && in.getDivMeasure() == out.getDivMeasure() {
|
if in.getMeasure() == out.getMeasure() && in.getDivMeasure() == out.getDivMeasure() {
|
||||||
if f := GetPrefixFactor(in.getPrefix(), out.getPrefix()); f(1.0) == factor {
|
if f := GetPrefixPrefixFactor(in.getPrefix(), out.getPrefix()); f(1.0) == factor {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(f(1.0))
|
fmt.Println(f(1.0))
|
||||||
@ -108,7 +108,73 @@ func TestUnitsDifferentPrefix(t *testing.T) {
|
|||||||
for _, c := range testCases {
|
for _, c := range testCases {
|
||||||
u := NewUnit(c.in)
|
u := NewUnit(c.in)
|
||||||
if (!u.Valid()) || (!compareUnitWithPrefix(u, c.want, c.prefixFactor)) {
|
if (!u.Valid()) || (!compareUnitWithPrefix(u, c.want, c.prefixFactor)) {
|
||||||
t.Errorf("func NewUnit(%q) == %q, want %q with factor %f", c.in, u.String(), c.want.String(), c.prefixFactor)
|
t.Errorf("GetPrefixPrefixFactor(%q, %q) invalid, want %q with factor %f", c.in, u.String(), c.want.String(), c.prefixFactor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnitPrefixConversion(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
prefixFactor float64
|
||||||
|
wantUnit Unit
|
||||||
|
}{
|
||||||
|
{"KBytes", "", 1000, NewUnit("Bytes")},
|
||||||
|
{"MBytes", "", 1e6, NewUnit("Bytes")},
|
||||||
|
{"MBytes", "G", 1e-3, NewUnit("GBytes")},
|
||||||
|
{"mb", "M", 1, NewUnit("MBytes")},
|
||||||
|
}
|
||||||
|
compareUnitPrefix := func(in Unit, out Prefix, factor float64, outUnit Unit) bool {
|
||||||
|
if in.Valid() {
|
||||||
|
conv, unit := GetUnitPrefixFactor(in, out)
|
||||||
|
value := conv(1.0)
|
||||||
|
if value == factor && unit.String() == outUnit.String() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range testCases {
|
||||||
|
u := NewUnit(c.in)
|
||||||
|
p := NewPrefix(c.want)
|
||||||
|
if (!u.Valid()) || (!compareUnitPrefix(u, p, c.prefixFactor, c.wantUnit)) {
|
||||||
|
t.Errorf("GetUnitPrefixFactor(%q, %q) invalid, want %q with factor %f", c.in, p.Prefix(), c.wantUnit.String(), c.prefixFactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrefixPrefixConversion(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
in string
|
||||||
|
want string
|
||||||
|
prefixFactor float64
|
||||||
|
}{
|
||||||
|
{"K", "", 1000},
|
||||||
|
{"M", "", 1e6},
|
||||||
|
{"M", "G", 1e-3},
|
||||||
|
{"", "M", 1e-6},
|
||||||
|
{"", "m", 1e3},
|
||||||
|
{"m", "n", 1e6},
|
||||||
|
//{"", "n", 1e9} does not work because of IEEE rounding problems
|
||||||
|
}
|
||||||
|
comparePrefixPrefix := func(in Prefix, out Prefix, factor float64) bool {
|
||||||
|
if in != InvalidPrefix && out != InvalidPrefix {
|
||||||
|
conv := GetPrefixPrefixFactor(in, out)
|
||||||
|
value := conv(1.0)
|
||||||
|
fmt.Println("1.0 -> ", value, ", want ", factor)
|
||||||
|
if value == factor {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range testCases {
|
||||||
|
i := NewPrefix(c.in)
|
||||||
|
o := NewPrefix(c.want)
|
||||||
|
if !comparePrefixPrefix(i, o, c.prefixFactor) {
|
||||||
|
t.Errorf("GetPrefixPrefixFactor(%q, %q) invalid, want %q with factor %f", c.in, c.want, o.Prefix(), c.prefixFactor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user