sanity check tests.

This commit is contained in:
Will Charczuk 2017-03-05 16:52:34 -08:00
parent 10950a3bf2
commit 8b34cb3bd7
8 changed files with 138 additions and 35 deletions

View File

@ -48,7 +48,33 @@ func drawChart(res http.ResponseWriter, req *http.Request) {
} }
func unit(res http.ResponseWriter, req *http.Request) {
graph := chart.Chart{
Height: 50,
Width: 50,
Canvas: chart.Style{
Padding: chart.Box{IsSet: true},
},
Background: chart.Style{
Padding: chart.Box{IsSet: true},
},
Series: []chart.Series{
chart.ContinuousSeries{
XValues: chart.Sequence.Float64(0, 4, 1),
YValues: chart.Sequence.Float64(0, 4, 1),
},
},
}
res.Header().Set("Content-Type", "image/png")
err := graph.Render(chart.PNG, res)
if err != nil {
log.Println(err.Error())
}
}
func main() { func main() {
http.HandleFunc("/", drawChart) http.HandleFunc("/", drawChart)
http.HandleFunc("/unit", unit)
log.Fatal(http.ListenAndServe(":8080", nil)) log.Fatal(http.ListenAndServe(":8080", nil))
} }

29
box.go
View File

@ -5,8 +5,25 @@ import (
"math" "math"
) )
var (
// BoxZero is a preset box that represents an intentional zero value.
BoxZero = Box{IsSet: true}
)
// NewBox returns a new (set) box.
func NewBox(top, left, right, bottom int) Box {
return Box{
IsSet: true,
Top: top,
Left: left,
Right: right,
Bottom: bottom,
}
}
// Box represents the main 4 dimensions of a box. // Box represents the main 4 dimensions of a box.
type Box struct { type Box struct {
IsSet bool
Top int Top int
Left int Left int
Right int Right int
@ -15,6 +32,9 @@ type Box struct {
// IsZero returns if the box is set or not. // IsZero returns if the box is set or not.
func (b Box) IsZero() bool { func (b Box) IsZero() bool {
if b.IsSet {
return false
}
return b.Top == 0 && b.Left == 0 && b.Right == 0 && b.Bottom == 0 return b.Top == 0 && b.Left == 0 && b.Right == 0 && b.Bottom == 0
} }
@ -25,7 +45,7 @@ func (b Box) String() string {
// GetTop returns a coalesced value with a default. // GetTop returns a coalesced value with a default.
func (b Box) GetTop(defaults ...int) int { func (b Box) GetTop(defaults ...int) int {
if b.Top == 0 { if !b.IsSet && b.Top == 0 {
if len(defaults) > 0 { if len(defaults) > 0 {
return defaults[0] return defaults[0]
} }
@ -36,7 +56,7 @@ func (b Box) GetTop(defaults ...int) int {
// GetLeft returns a coalesced value with a default. // GetLeft returns a coalesced value with a default.
func (b Box) GetLeft(defaults ...int) int { func (b Box) GetLeft(defaults ...int) int {
if b.Left == 0 { if !b.IsSet && b.Left == 0 {
if len(defaults) > 0 { if len(defaults) > 0 {
return defaults[0] return defaults[0]
} }
@ -47,7 +67,7 @@ func (b Box) GetLeft(defaults ...int) int {
// GetRight returns a coalesced value with a default. // GetRight returns a coalesced value with a default.
func (b Box) GetRight(defaults ...int) int { func (b Box) GetRight(defaults ...int) int {
if b.Right == 0 { if !b.IsSet && b.Right == 0 {
if len(defaults) > 0 { if len(defaults) > 0 {
return defaults[0] return defaults[0]
} }
@ -58,7 +78,7 @@ func (b Box) GetRight(defaults ...int) int {
// GetBottom returns a coalesced value with a default. // GetBottom returns a coalesced value with a default.
func (b Box) GetBottom(defaults ...int) int { func (b Box) GetBottom(defaults ...int) int {
if b.Bottom == 0 { if !b.IsSet && b.Bottom == 0 {
if len(defaults) > 0 { if len(defaults) > 0 {
return defaults[0] return defaults[0]
} }
@ -91,6 +111,7 @@ func (b Box) Aspect() float64 {
// Clone returns a new copy of the box. // Clone returns a new copy of the box.
func (b Box) Clone() Box { func (b Box) Clone() Box {
return Box{ return Box{
IsSet: b.IsSet,
Top: b.Top, Top: b.Top,
Left: b.Left, Left: b.Left,
Right: b.Right, Right: b.Right,

View File

@ -109,9 +109,9 @@ func TestBoxConstrain(t *testing.T) {
func TestBoxOuterConstrain(t *testing.T) { func TestBoxOuterConstrain(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
box := Box{0, 0, 100, 100} box := NewBox(0, 0, 100, 100)
canvas := Box{5, 5, 95, 95} canvas := NewBox(5, 5, 95, 95)
taller := Box{-10, 5, 50, 50} taller := NewBox(-10, 5, 50, 50)
c := canvas.OuterConstrain(box, taller) c := canvas.OuterConstrain(box, taller)
assert.Equal(15, c.Top, c.String()) assert.Equal(15, c.Top, c.String())
@ -119,7 +119,7 @@ func TestBoxOuterConstrain(t *testing.T) {
assert.Equal(95, c.Right, c.String()) assert.Equal(95, c.Right, c.String())
assert.Equal(95, c.Bottom, c.String()) assert.Equal(95, c.Bottom, c.String())
wider := Box{5, 5, 110, 50} wider := NewBox(5, 5, 110, 50)
d := canvas.OuterConstrain(box, wider) d := canvas.OuterConstrain(box, wider)
assert.Equal(5, d.Top, d.String()) assert.Equal(5, d.Top, d.String())
assert.Equal(5, d.Left, d.String()) assert.Equal(5, d.Left, d.String())

View File

@ -2,6 +2,8 @@ package chart
import ( import (
"bytes" "bytes"
"image"
"image/png"
"math" "math"
"testing" "testing"
"time" "time"
@ -484,10 +486,22 @@ func TestChartCheckRangesWithRanges(t *testing.T) {
assert.Nil(c.checkRanges(xr, yr, yra)) assert.Nil(c.checkRanges(xr, yr, yra))
} }
func at(i image.Image, x, y int) drawing.Color {
return drawing.ColorFromAlphaMixedRGBA(i.At(x, y).RGBA())
}
func TestChartE2ELine(t *testing.T) { func TestChartE2ELine(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
c := Chart{ c := Chart{
Height: 50,
Width: 50,
Canvas: Style{
Padding: Box{IsSet: true},
},
Background: Style{
Padding: Box{IsSet: true},
},
Series: []Series{ Series: []Series{
ContinuousSeries{ ContinuousSeries{
XValues: Sequence.Float64(0, 4, 1), XValues: Sequence.Float64(0, 4, 1),
@ -502,5 +516,60 @@ func TestChartE2ELine(t *testing.T) {
// do color tests ... // do color tests ...
i, err := png.Decode(buffer)
assert.Nil(err)
// test the bottom and top of the line
assert.Equal(drawing.ColorWhite, at(i, 0, 0))
assert.Equal(drawing.ColorWhite, at(i, 49, 49))
// test a line mid point
defaultSeriesColor := GetDefaultColor(0)
assert.Equal(defaultSeriesColor, at(i, 0, 49))
assert.Equal(defaultSeriesColor, at(i, 49, 0))
assert.Equal(drawing.ColorFromHex("bddbf6"), at(i, 24, 24))
}
func TestChartE2ELineWithFill(t *testing.T) {
assert := assert.New(t)
c := Chart{
Height: 50,
Width: 50,
Canvas: Style{
Padding: Box{IsSet: true},
},
Background: Style{
Padding: Box{IsSet: true},
},
Series: []Series{
ContinuousSeries{
Style: Style{
Show: true,
StrokeColor: drawing.ColorBlue,
FillColor: drawing.ColorRed,
},
XValues: Sequence.Float64(0, 4, 1),
YValues: Sequence.Float64(0, 4, 1),
},
},
}
var buffer = &bytes.Buffer{}
err := c.Render(PNG, buffer)
assert.Nil(err)
// do color tests ...
i, err := png.Decode(buffer)
assert.Nil(err)
// test the bottom and top of the line
assert.Equal(drawing.ColorWhite, at(i, 0, 0))
assert.Equal(drawing.ColorRed, at(i, 49, 49))
// test a line mid point
defaultSeriesColor := drawing.ColorBlue
assert.Equal(defaultSeriesColor, at(i, 0, 49))
assert.Equal(defaultSeriesColor, at(i, 49, 0))
} }

View File

@ -104,6 +104,16 @@ func (c Color) Equals(other Color) bool {
c.A == other.A c.A == other.A
} }
// AverageWith averages two colors.
func (c Color) AverageWith(other Color) Color {
return Color{
R: (c.R + other.R) >> 1,
G: (c.G + other.G) >> 1,
B: (c.B + other.B) >> 1,
A: c.A,
}
}
// String returns a css string representation of the color. // String returns a css string representation of the color.
func (c Color) String() string { func (c Color) String() string {
fa := float64(c.A) / float64(255) fa := float64(c.A) / float64(255)

View File

@ -1,23 +0,0 @@
package drawing
import "image"
// Image is a helper wraper that allows (sane) access to pixel info.
type Image struct {
Inner *image.RGBA
}
// Width returns the image's width in pixels.
func (i Image) Width() int {
return i.Inner.Rect.Size().X
}
// Height returns the image's height in pixels.
func (i Image) Height() int {
return i.Inner.Rect.Size().Y
}
// At returns a pixel color at a given x/y.
func (i Image) At(x, y int) Color {
return ColorFromAlphaMixedRGBA(i.Inner.At(x, y).RGBA())
}

View File

@ -61,7 +61,7 @@ func TestXAxisMeasure(t *testing.T) {
assert.Nil(err) assert.Nil(err)
ticks := []Tick{{Value: 1.0, Label: "1.0"}, {Value: 2.0, Label: "2.0"}, {Value: 3.0, Label: "3.0"}} ticks := []Tick{{Value: 1.0, Label: "1.0"}, {Value: 2.0, Label: "2.0"}, {Value: 3.0, Label: "3.0"}}
xa := XAxis{} xa := XAxis{}
xab := xa.Measure(r, Box{0, 0, 100, 100}, &ContinuousRange{Min: 1.0, Max: 3.0, Domain: 100}, style, ticks) xab := xa.Measure(r, NewBox(0, 0, 100, 100), &ContinuousRange{Min: 1.0, Max: 3.0, Domain: 100}, style, ticks)
assert.Equal(122, xab.Width()) assert.Equal(122, xab.Width())
assert.Equal(21, xab.Height()) assert.Equal(21, xab.Height())
} }

View File

@ -61,7 +61,7 @@ func TestYAxisMeasure(t *testing.T) {
assert.Nil(err) assert.Nil(err)
ticks := []Tick{{Value: 1.0, Label: "1.0"}, {Value: 2.0, Label: "2.0"}, {Value: 3.0, Label: "3.0"}} ticks := []Tick{{Value: 1.0, Label: "1.0"}, {Value: 2.0, Label: "2.0"}, {Value: 3.0, Label: "3.0"}}
ya := YAxis{} ya := YAxis{}
yab := ya.Measure(r, Box{0, 0, 100, 100}, &ContinuousRange{Min: 1.0, Max: 3.0, Domain: 100}, style, ticks) yab := ya.Measure(r, NewBox(0, 0, 100, 100), &ContinuousRange{Min: 1.0, Max: 3.0, Domain: 100}, style, ticks)
assert.Equal(32, yab.Width()) assert.Equal(32, yab.Width())
assert.Equal(110, yab.Height()) assert.Equal(110, yab.Height())
} }
@ -79,7 +79,7 @@ func TestYAxisSecondaryMeasure(t *testing.T) {
assert.Nil(err) assert.Nil(err)
ticks := []Tick{{Value: 1.0, Label: "1.0"}, {Value: 2.0, Label: "2.0"}, {Value: 3.0, Label: "3.0"}} ticks := []Tick{{Value: 1.0, Label: "1.0"}, {Value: 2.0, Label: "2.0"}, {Value: 3.0, Label: "3.0"}}
ya := YAxis{AxisType: YAxisSecondary} ya := YAxis{AxisType: YAxisSecondary}
yab := ya.Measure(r, Box{0, 0, 100, 100}, &ContinuousRange{Min: 1.0, Max: 3.0, Domain: 100}, style, ticks) yab := ya.Measure(r, NewBox(0, 0, 100, 100), &ContinuousRange{Min: 1.0, Max: 3.0, Domain: 100}, style, ticks)
assert.Equal(32, yab.Width()) assert.Equal(32, yab.Width())
assert.Equal(110, yab.Height()) assert.Equal(110, yab.Height())
} }