mirror of
https://github.com/gonum/gonum.git
synced 2025-10-04 06:46:29 +08:00
758 lines
17 KiB
Go
758 lines
17 KiB
Go
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"go/format"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
"text/template"
|
|
|
|
"gonum.org/v1/gonum/unit"
|
|
)
|
|
|
|
type Unit struct {
|
|
Name string
|
|
Receiver string
|
|
Offset int // From normal (for example, mass base unit is kg, not kg)
|
|
PrintString string // print string for the unit (kg for mass)
|
|
ExtraConstant []Constant
|
|
Suffix string
|
|
Singular string
|
|
TypeComment string // Text to comment the type
|
|
Dimensions []Dimension
|
|
ErForm string //For Xxxer interface
|
|
}
|
|
|
|
type Dimension struct {
|
|
Name string
|
|
Power int
|
|
}
|
|
|
|
func (u Unit) Units() string {
|
|
dims := make(unit.Dimensions)
|
|
for _, d := range u.Dimensions {
|
|
dims[dimOf[d.Name]] = d.Power
|
|
}
|
|
return dims.String()
|
|
}
|
|
|
|
const (
|
|
AngleName string = "AngleDim"
|
|
CurrentName string = "CurrentDim"
|
|
LengthName string = "LengthDim"
|
|
LuminousIntensityName string = "LuminousIntensityDim"
|
|
MassName string = "MassDim"
|
|
MoleName string = "MoleDim"
|
|
TemperatureName string = "TemperatureDim"
|
|
TimeName string = "TimeDim"
|
|
)
|
|
|
|
var dimOf = map[string]unit.Dimension{
|
|
"AngleDim": unit.AngleDim,
|
|
"CurrentDim": unit.CurrentDim,
|
|
"LengthDim": unit.LengthDim,
|
|
"LuminousIntensityDim": unit.LuminousIntensityDim,
|
|
"MassDim": unit.MassDim,
|
|
"MoleDim": unit.MoleDim,
|
|
"TemperatureDim": unit.TemperatureDim,
|
|
"TimeDim": unit.TimeDim,
|
|
}
|
|
|
|
type Constant struct {
|
|
Name string
|
|
Value string
|
|
}
|
|
|
|
type Prefix struct {
|
|
Name string
|
|
Power int
|
|
}
|
|
|
|
var Prefixes = []Prefix{
|
|
{
|
|
Name: "Yotta",
|
|
Power: 24,
|
|
},
|
|
{
|
|
Name: "Zetta",
|
|
Power: 21,
|
|
},
|
|
{
|
|
Name: "Exa",
|
|
Power: 18,
|
|
},
|
|
{
|
|
Name: "Peta",
|
|
Power: 15,
|
|
},
|
|
{
|
|
Name: "Tera",
|
|
Power: 12,
|
|
},
|
|
{
|
|
Name: "Giga",
|
|
Power: 9,
|
|
},
|
|
{
|
|
Name: "Mega",
|
|
Power: 6,
|
|
},
|
|
{
|
|
Name: "Kilo",
|
|
Power: 3,
|
|
},
|
|
{
|
|
Name: "Hecto",
|
|
Power: 2,
|
|
},
|
|
{
|
|
Name: "Deca",
|
|
Power: 1,
|
|
},
|
|
{
|
|
Name: "",
|
|
Power: 0,
|
|
},
|
|
{
|
|
Name: "Deci",
|
|
Power: -1,
|
|
},
|
|
{
|
|
Name: "Centi",
|
|
Power: -2,
|
|
},
|
|
{
|
|
Name: "Milli",
|
|
Power: -3,
|
|
},
|
|
{
|
|
Name: "Micro",
|
|
Power: -6,
|
|
},
|
|
{
|
|
Name: "Nano",
|
|
Power: -9,
|
|
},
|
|
{
|
|
Name: "Pico",
|
|
Power: -12,
|
|
},
|
|
{
|
|
Name: "Femto",
|
|
Power: -15,
|
|
},
|
|
{
|
|
Name: "Atto",
|
|
Power: -18,
|
|
},
|
|
{
|
|
Name: "Zepto",
|
|
Power: -21,
|
|
},
|
|
{
|
|
Name: "Yocto",
|
|
Power: -24,
|
|
},
|
|
}
|
|
|
|
var Units = []Unit{
|
|
// Base units.
|
|
{
|
|
Name: "Angle",
|
|
Receiver: "a",
|
|
PrintString: "rad",
|
|
Suffix: "rad",
|
|
Singular: "Rad",
|
|
TypeComment: "Angle represents an angle in radians",
|
|
Dimensions: []Dimension{
|
|
{Name: AngleName, Power: 1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Current",
|
|
Receiver: "i",
|
|
PrintString: "A",
|
|
Suffix: "ampere",
|
|
Singular: "Ampere",
|
|
TypeComment: "Current represents a current in Amperes",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: 1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Length",
|
|
Receiver: "l",
|
|
PrintString: "m",
|
|
Suffix: "metre",
|
|
Singular: "Metre",
|
|
TypeComment: "Length represents a length in metres",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 1},
|
|
},
|
|
},
|
|
{
|
|
Name: "LuminousIntensity",
|
|
Receiver: "j",
|
|
PrintString: "cd",
|
|
Suffix: "candela",
|
|
Singular: "Candela",
|
|
TypeComment: "Candela represents a luminous intensity in candela",
|
|
Dimensions: []Dimension{
|
|
{Name: LuminousIntensityName, Power: 1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Mass",
|
|
Receiver: "m",
|
|
Offset: -3,
|
|
PrintString: "kg",
|
|
Suffix: "gram",
|
|
Singular: "Gram",
|
|
TypeComment: "Mass represents a mass in kilograms",
|
|
Dimensions: []Dimension{
|
|
{Name: MassName, Power: 1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Mole",
|
|
Receiver: "n",
|
|
PrintString: "mol",
|
|
Suffix: "mol",
|
|
Singular: "mol",
|
|
TypeComment: "Mole represents an amount in moles",
|
|
Dimensions: []Dimension{
|
|
{Name: MoleName, Power: 1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Temperature",
|
|
Receiver: "t",
|
|
PrintString: "K",
|
|
Suffix: "kelvin",
|
|
Singular: "Kelvin",
|
|
TypeComment: "Temperature represents a temperature in Kelvin",
|
|
Dimensions: []Dimension{
|
|
{Name: TemperatureName, Power: 1},
|
|
},
|
|
ErForm: "Temperaturer",
|
|
},
|
|
{
|
|
Name: "Time",
|
|
Receiver: "t",
|
|
PrintString: "s",
|
|
Suffix: "second",
|
|
Singular: "Second",
|
|
TypeComment: "Time represents a time in seconds",
|
|
ExtraConstant: []Constant{
|
|
{Name: "Hour", Value: "3600"},
|
|
{Name: "Minute", Value: "60"},
|
|
},
|
|
Dimensions: []Dimension{
|
|
{Name: TimeName, Power: 1},
|
|
},
|
|
ErForm: "Timer",
|
|
},
|
|
|
|
// Derived units.
|
|
{
|
|
Name: "AbsorbedRadioactiveDose",
|
|
Receiver: "a",
|
|
PrintString: "Gy",
|
|
Suffix: "gray",
|
|
Singular: "Gray",
|
|
TypeComment: "AbsorbedRadioactiveDose is a measure of absorbed dose of ionizing radiation in grays",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 2},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
},
|
|
{
|
|
Name: "Acceleration",
|
|
Receiver: "a",
|
|
PrintString: "m s^-2",
|
|
TypeComment: "Acceleration represents an acceleration in metres per second squared",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
},
|
|
{
|
|
Name: "Area",
|
|
Receiver: "a",
|
|
PrintString: "m^2",
|
|
TypeComment: "Area represents and area in square metres",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 2},
|
|
},
|
|
},
|
|
{
|
|
Name: "Radioactivity",
|
|
Receiver: "r",
|
|
PrintString: "Bq",
|
|
Suffix: "becquerel",
|
|
Singular: "Becquerel",
|
|
TypeComment: "Radioactivity represents a rate of radioactive decay in becquerels",
|
|
Dimensions: []Dimension{
|
|
{Name: TimeName, Power: -1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Capacitance",
|
|
Receiver: "cp",
|
|
PrintString: "F",
|
|
Suffix: "farad",
|
|
Singular: "Farad",
|
|
TypeComment: "Capacitance represents an electrical capacitance in Farads",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: 2},
|
|
{Name: LengthName, Power: -2},
|
|
{Name: MassName, Power: -1},
|
|
{Name: TimeName, Power: 4},
|
|
},
|
|
ErForm: "Capacitancer",
|
|
},
|
|
{
|
|
Name: "Charge",
|
|
Receiver: "ch",
|
|
PrintString: "C",
|
|
Suffix: "coulomb",
|
|
Singular: "coulomb",
|
|
TypeComment: "Charge represents an electric charge in Coulombs",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: 1},
|
|
{Name: TimeName, Power: 1},
|
|
},
|
|
ErForm: "Charger",
|
|
},
|
|
{
|
|
Name: "Conductance",
|
|
Receiver: "co",
|
|
PrintString: "S",
|
|
Suffix: "siemens",
|
|
Singular: "Siemens",
|
|
TypeComment: "Conductance represents an electrical conductance in Siemens",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: 2},
|
|
{Name: LengthName, Power: -2},
|
|
{Name: MassName, Power: -1},
|
|
{Name: TimeName, Power: 3},
|
|
},
|
|
ErForm: "Conductancer",
|
|
},
|
|
{
|
|
Name: "EquivalentRadioactiveDose",
|
|
Receiver: "a",
|
|
PrintString: "Sy",
|
|
Suffix: "sievert",
|
|
Singular: "Sievert",
|
|
TypeComment: "EquivalentRadioactiveDose is a measure of equivalent dose of ionizing radiation in sieverts",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 2},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
},
|
|
{
|
|
Name: "Energy",
|
|
Receiver: "e",
|
|
PrintString: "J",
|
|
Suffix: "joule",
|
|
Singular: "Joule",
|
|
TypeComment: "Energy represents a quantity of energy in Joules",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
},
|
|
{
|
|
Name: "Frequency",
|
|
Receiver: "f",
|
|
PrintString: "Hz",
|
|
Suffix: "hertz",
|
|
Singular: "Hertz",
|
|
TypeComment: "Frequency represents a frequency in Hertz",
|
|
Dimensions: []Dimension{
|
|
{Name: TimeName, Power: -1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Force",
|
|
Receiver: "f",
|
|
PrintString: "N",
|
|
Suffix: "newton",
|
|
Singular: "Newton",
|
|
TypeComment: "Force represents a force in Newtons",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 1},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
ErForm: "Forcer",
|
|
},
|
|
{
|
|
Name: "Inductance",
|
|
Receiver: "i",
|
|
PrintString: "H",
|
|
Suffix: "henry",
|
|
Singular: "Henry",
|
|
TypeComment: "Inductance represents an electrical inductance in Henry",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: -2},
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
ErForm: "Inductancer",
|
|
},
|
|
{
|
|
Name: "Power",
|
|
Receiver: "pw",
|
|
PrintString: "W",
|
|
Suffix: "watt",
|
|
Singular: "Watt",
|
|
TypeComment: "Power represents a power in Watts",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -3},
|
|
},
|
|
},
|
|
{
|
|
Name: "Resistance",
|
|
Receiver: "r",
|
|
PrintString: "Ω",
|
|
Suffix: "ohm",
|
|
Singular: "Ohm",
|
|
TypeComment: "Resistance represents an electrical resistance, impedance or reactance in Ohms",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: -2},
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -3},
|
|
},
|
|
ErForm: "Resistancer",
|
|
},
|
|
{
|
|
Name: "MagneticFlux",
|
|
Receiver: "m",
|
|
PrintString: "Wb",
|
|
Suffix: "weber",
|
|
Singular: "Weber",
|
|
TypeComment: "MagneticFlux represents a magnetic flux in Weber",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: -1},
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
},
|
|
{
|
|
Name: "MagneticFluxDensity",
|
|
Receiver: "m",
|
|
PrintString: "T",
|
|
Suffix: "tesla",
|
|
Singular: "Tesla",
|
|
TypeComment: "MagneticFluxDensity represents a magnetic flux density in Tesla",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: -1},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
},
|
|
{
|
|
Name: "Pressure",
|
|
Receiver: "pr",
|
|
PrintString: "Pa",
|
|
Suffix: "pascal",
|
|
Singular: "Pascal",
|
|
TypeComment: "Pressure represents a pressure in Pascals",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: -1},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
ErForm: "Pressurer",
|
|
},
|
|
{
|
|
Name: "Torque",
|
|
Receiver: "t",
|
|
PrintString: "N m",
|
|
Suffix: "newtonmetre",
|
|
Singular: "Newtonmetre",
|
|
TypeComment: "Torque represents a torque in Newton metres",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -2},
|
|
},
|
|
ErForm: "Torquer",
|
|
},
|
|
{
|
|
Name: "Velocity",
|
|
Receiver: "v",
|
|
PrintString: "m s^-1",
|
|
TypeComment: "Velocity represents a velocity in metres per second",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 1},
|
|
{Name: TimeName, Power: -1},
|
|
},
|
|
},
|
|
{
|
|
Name: "Voltage",
|
|
Receiver: "v",
|
|
PrintString: "V",
|
|
Suffix: "volt",
|
|
Singular: "Volt",
|
|
TypeComment: "Voltage represents a voltage in Volts",
|
|
Dimensions: []Dimension{
|
|
{Name: CurrentName, Power: -1},
|
|
{Name: LengthName, Power: 2},
|
|
{Name: MassName, Power: 1},
|
|
{Name: TimeName, Power: -3},
|
|
},
|
|
ErForm: "Voltager",
|
|
},
|
|
{
|
|
Name: "Volume",
|
|
Receiver: "v",
|
|
Offset: -3,
|
|
PrintString: "m^3",
|
|
Suffix: "litre",
|
|
Singular: "Litre",
|
|
TypeComment: "Volume represents a volume in cubic metres",
|
|
Dimensions: []Dimension{
|
|
{Name: LengthName, Power: 3},
|
|
},
|
|
},
|
|
}
|
|
|
|
// Generate generates a file for each of the units
|
|
func main() {
|
|
for _, unit := range Units {
|
|
generate(unit)
|
|
generateTest(unit)
|
|
}
|
|
}
|
|
|
|
const headerTemplate = `// Code generated by "go generate gonum.org/v1/gonum/unit”; DO NOT EDIT.
|
|
|
|
// Copyright ©2014 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package unit
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// {{.TypeComment}}.
|
|
type {{.Name}} float64
|
|
`
|
|
|
|
var header = template.Must(template.New("header").Parse(headerTemplate))
|
|
|
|
const constTemplate = `
|
|
const(
|
|
{{$unit := .Unit}}
|
|
{{range $unit.ExtraConstant}} {{.Name}} {{$unit.Name}} = {{.Value}}
|
|
{{end}}
|
|
{{$prefixes := .Prefixes}}
|
|
{{range $prefixes}} {{if .Name}} {{.Name}}{{$unit.Suffix}} {{else}} {{$unit.Singular}} {{end}} {{$unit.Name}} = {{if .Power}} 1e{{.Power}} {{else}} 1.0 {{end}}
|
|
{{end}}
|
|
)
|
|
`
|
|
|
|
var prefix = template.Must(template.New("prefix").Parse(constTemplate))
|
|
|
|
const methodTemplate = `
|
|
// Unit converts the {{.Name}} to a *Unit
|
|
func ({{.Receiver}} {{.Name}}) Unit() *Unit {
|
|
return New(float64({{.Receiver}}), Dimensions{
|
|
{{range .Dimensions}} {{.Name}}: {{.Power}},
|
|
{{end}}
|
|
})
|
|
}
|
|
|
|
// {{.Name}} allows {{.Name}} to implement a {{if .ErForm}}{{.ErForm}}{{else}}{{.Name}}er{{end}} interface
|
|
func ({{.Receiver}} {{.Name}}) {{.Name}}() {{.Name}} {
|
|
return {{.Receiver}}
|
|
}
|
|
|
|
// From converts the unit into the receiver. From returns an
|
|
// error if there is a mismatch in dimension
|
|
func ({{.Receiver}} *{{.Name}}) From(u Uniter) error {
|
|
if !DimensionsMatch(u, {{if .Singular}}{{.Singular}}{{else}}{{.Name}}(0){{end}}){
|
|
*{{.Receiver}} = {{.Name}}(math.NaN())
|
|
return errors.New("Dimension mismatch")
|
|
}
|
|
*{{.Receiver}} = {{.Name}}(u.Unit().Value())
|
|
return nil
|
|
}
|
|
`
|
|
|
|
var methods = template.Must(template.New("methods").Parse(methodTemplate))
|
|
|
|
const formatTemplate = `
|
|
func ({{.Receiver}} {{.Name}}) Format(fs fmt.State, c rune) {
|
|
switch c {
|
|
case 'v':
|
|
if fs.Flag('#') {
|
|
fmt.Fprintf(fs, "%T(%v)", {{.Receiver}}, float64({{.Receiver}}))
|
|
return
|
|
}
|
|
fallthrough
|
|
case 'e', 'E', 'f', 'F', 'g', 'G':
|
|
p, pOk := fs.Precision()
|
|
w, wOk := fs.Width()
|
|
const unit = " {{.PrintString}}"
|
|
switch {
|
|
case pOk && wOk:
|
|
fmt.Fprintf(fs, "%*.*"+string(c), pos(w-utf8.RuneCount([]byte(unit))), p, float64({{.Receiver}}))
|
|
case pOk:
|
|
fmt.Fprintf(fs, "%.*"+string(c), p, float64({{.Receiver}}))
|
|
case wOk:
|
|
fmt.Fprintf(fs, "%*"+string(c), pos(w-utf8.RuneCount([]byte(unit))), float64({{.Receiver}}))
|
|
default:
|
|
fmt.Fprintf(fs, "%"+string(c), float64({{.Receiver}}))
|
|
}
|
|
fmt.Fprint(fs, unit)
|
|
default:
|
|
fmt.Fprintf(fs, "%%!%c(%T=%g {{.PrintString}})", c, {{.Receiver}}, float64({{.Receiver}}))
|
|
}
|
|
}
|
|
`
|
|
|
|
var form = template.Must(template.New("format").Parse(formatTemplate))
|
|
|
|
func generate(unit Unit) {
|
|
lowerName := strings.ToLower(unit.Name)
|
|
filename := lowerName + ".go"
|
|
f, err := os.Create(filename)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
// Need to define new prefixes because text/template can't do math.
|
|
// Need to do math because kilogram = 1 not 10^3
|
|
|
|
prefixes := make([]Prefix, len(Prefixes))
|
|
for i, p := range Prefixes {
|
|
prefixes[i].Name = p.Name
|
|
prefixes[i].Power = p.Power + unit.Offset
|
|
}
|
|
|
|
data := struct {
|
|
Prefixes []Prefix
|
|
Unit Unit
|
|
}{
|
|
prefixes,
|
|
unit,
|
|
}
|
|
|
|
buf := bytes.NewBuffer(make([]byte, 0))
|
|
|
|
err = header.Execute(buf, unit)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
if unit.Singular != "" {
|
|
err = prefix.Execute(buf, data)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
err = methods.Execute(buf, unit)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
err = form.Execute(buf, unit)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
b, err := format.Source(buf.Bytes())
|
|
if err != nil {
|
|
f.Write(buf.Bytes()) // This is here to debug bad format
|
|
log.Fatalf("error formatting %q: %s", unit.Name, err)
|
|
}
|
|
|
|
f.Write(b)
|
|
}
|
|
|
|
const testTemplate = `// Code generated by "go generate gonum.org/v1/gonum/unit; DO NOT EDIT.
|
|
|
|
// Copyright ©2019 The Gonum Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package unit
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
func Test{{.Name}}Format(t *testing.T) {
|
|
for _, test := range []struct{
|
|
value {{.Name}}
|
|
format string
|
|
want string
|
|
}{
|
|
{1.23456789, "%v", "1.23456789 {{.PrintString}}"},
|
|
{1.23456789, "%.1v", "1 {{.PrintString}}"},
|
|
{1.23456789, "%20.1v", "{{$s := printf "1 %s" .PrintString}}{{printf "%20s" $s}}"},
|
|
{1.23456789, "%20v", "{{$s := printf "1.23456789 %s" .PrintString}}{{printf "%20s" $s}}"},
|
|
{1.23456789, "%1v", "1.23456789 {{.PrintString}}"},
|
|
{1.23456789, "%#v", "unit.{{.Name}}(1.23456789)"},
|
|
{1.23456789, "%s", "%!s(unit.{{.Name}}=1.23456789 {{.PrintString}})"},
|
|
} {
|
|
got := fmt.Sprintf(test.format, test.value)
|
|
if got != test.want {
|
|
t.Errorf("Format %q %v: got: %q want: %q", test.format, float64(test.value), got, test.want)
|
|
}
|
|
}
|
|
}
|
|
`
|
|
|
|
var tests = template.Must(template.New("test").Parse(testTemplate))
|
|
|
|
func generateTest(unit Unit) {
|
|
lowerName := strings.ToLower(unit.Name)
|
|
filename := lowerName + "_test.go"
|
|
f, err := os.Create(filename)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer f.Close()
|
|
|
|
buf := bytes.NewBuffer(make([]byte, 0))
|
|
|
|
err = tests.Execute(buf, unit)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
b, err := format.Source(buf.Bytes())
|
|
if err != nil {
|
|
f.Write(buf.Bytes()) // This is here to debug bad format.
|
|
log.Fatalf("error formatting test for %q: %s", unit.Name, err)
|
|
}
|
|
|
|
f.Write(b)
|
|
}
|