package chart import ( "bytes" "image" "image/png" "math" "testing" "time" "github.com/wcharczuk/go-chart/v2/drawing" "github.com/wcharczuk/go-chart/v2/testutil" ) func TestChartGetDPI(t *testing.T) { // replaced new assertions helper unset := Chart{} testutil.AssertEqual(t, DefaultDPI, unset.GetDPI()) testutil.AssertEqual(t, 192, unset.GetDPI(192)) set := Chart{DPI: 128} testutil.AssertEqual(t, 128, set.GetDPI()) testutil.AssertEqual(t, 128, set.GetDPI(192)) } func TestChartGetFont(t *testing.T) { // replaced new assertions helper f, err := GetDefaultFont() testutil.AssertNil(t, err) unset := Chart{} testutil.AssertNil(t, unset.GetFont()) set := Chart{Font: f} testutil.AssertNotNil(t, set.GetFont()) } func TestChartGetWidth(t *testing.T) { // replaced new assertions helper unset := Chart{} testutil.AssertEqual(t, DefaultChartWidth, unset.GetWidth()) set := Chart{Width: DefaultChartWidth + 10} testutil.AssertEqual(t, DefaultChartWidth+10, set.GetWidth()) } func TestChartGetHeight(t *testing.T) { // replaced new assertions helper unset := Chart{} testutil.AssertEqual(t, DefaultChartHeight, unset.GetHeight()) set := Chart{Height: DefaultChartHeight + 10} testutil.AssertEqual(t, DefaultChartHeight+10, set.GetHeight()) } func TestChartGetRanges(t *testing.T) { // replaced new assertions helper c := Chart{ Series: []Series{ ContinuousSeries{ XValues: []float64{-2.0, -1.0, 0, 1.0, 2.0}, YValues: []float64{1.0, 2.0, 3.0, 4.0, 4.5}, }, ContinuousSeries{ XValues: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, YValues: []float64{-2.1, -1.0, 0, 1.0, 2.0}, }, ContinuousSeries{ YAxis: YAxisSecondary, XValues: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, YValues: []float64{10.0, 11.0, 12.0, 13.0, 14.0}, }, }, } xrange, yrange, yrangeAlt := c.getRanges() testutil.AssertEqual(t, -2.0, xrange.GetMin()) testutil.AssertEqual(t, 5.0, xrange.GetMax()) testutil.AssertEqual(t, -2.1, yrange.GetMin()) testutil.AssertEqual(t, 4.5, yrange.GetMax()) testutil.AssertEqual(t, 10.0, yrangeAlt.GetMin()) testutil.AssertEqual(t, 14.0, yrangeAlt.GetMax()) cSet := Chart{ XAxis: XAxis{ Range: &ContinuousRange{Min: 9.8, Max: 19.8}, }, YAxis: YAxis{ Range: &ContinuousRange{Min: 9.9, Max: 19.9}, }, YAxisSecondary: YAxis{ Range: &ContinuousRange{Min: 9.7, Max: 19.7}, }, Series: []Series{ ContinuousSeries{ XValues: []float64{-2.0, -1.0, 0, 1.0, 2.0}, YValues: []float64{1.0, 2.0, 3.0, 4.0, 4.5}, }, ContinuousSeries{ XValues: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, YValues: []float64{-2.1, -1.0, 0, 1.0, 2.0}, }, ContinuousSeries{ YAxis: YAxisSecondary, XValues: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, YValues: []float64{10.0, 11.0, 12.0, 13.0, 14.0}, }, }, } xr2, yr2, yra2 := cSet.getRanges() testutil.AssertEqual(t, 9.8, xr2.GetMin()) testutil.AssertEqual(t, 19.8, xr2.GetMax()) testutil.AssertEqual(t, 9.9, yr2.GetMin()) testutil.AssertEqual(t, 19.9, yr2.GetMax()) testutil.AssertEqual(t, 9.7, yra2.GetMin()) testutil.AssertEqual(t, 19.7, yra2.GetMax()) } func TestChartGetRangesUseTicks(t *testing.T) { // replaced new assertions helper // this test asserts that ticks should supercede manual ranges when generating the overall ranges. c := Chart{ YAxis: YAxis{ Ticks: []Tick{ {0.0, "Zero"}, {1.0, "1.0"}, {2.0, "2.0"}, {3.0, "3.0"}, {4.0, "4.0"}, {5.0, "Five"}, }, Range: &ContinuousRange{ Min: -5.0, Max: 5.0, }, }, Series: []Series{ ContinuousSeries{ XValues: []float64{-2.0, -1.0, 0, 1.0, 2.0}, YValues: []float64{1.0, 2.0, 3.0, 4.0, 4.5}, }, }, } xr, yr, yar := c.getRanges() testutil.AssertEqual(t, -2.0, xr.GetMin()) testutil.AssertEqual(t, 2.0, xr.GetMax()) testutil.AssertEqual(t, 0.0, yr.GetMin()) testutil.AssertEqual(t, 5.0, yr.GetMax()) testutil.AssertTrue(t, yar.IsZero(), yar.String()) } func TestChartGetRangesUseUserRanges(t *testing.T) { // replaced new assertions helper c := Chart{ YAxis: YAxis{ Range: &ContinuousRange{ Min: -5.0, Max: 5.0, }, }, Series: []Series{ ContinuousSeries{ XValues: []float64{-2.0, -1.0, 0, 1.0, 2.0}, YValues: []float64{1.0, 2.0, 3.0, 4.0, 4.5}, }, }, } xr, yr, yar := c.getRanges() testutil.AssertEqual(t, -2.0, xr.GetMin()) testutil.AssertEqual(t, 2.0, xr.GetMax()) testutil.AssertEqual(t, -5.0, yr.GetMin()) testutil.AssertEqual(t, 5.0, yr.GetMax()) testutil.AssertTrue(t, yar.IsZero(), yar.String()) } func TestChartGetBackgroundStyle(t *testing.T) { // replaced new assertions helper c := Chart{ Background: Style{ FillColor: drawing.ColorBlack, }, } bs := c.getBackgroundStyle() testutil.AssertEqual(t, bs.FillColor.String(), drawing.ColorBlack.String()) } func TestChartGetCanvasStyle(t *testing.T) { // replaced new assertions helper c := Chart{ Canvas: Style{ FillColor: drawing.ColorBlack, }, } bs := c.getCanvasStyle() testutil.AssertEqual(t, bs.FillColor.String(), drawing.ColorBlack.String()) } func TestChartGetDefaultCanvasBox(t *testing.T) { // replaced new assertions helper c := Chart{} canvasBoxDefault := c.getDefaultCanvasBox() testutil.AssertFalse(t, canvasBoxDefault.IsZero()) testutil.AssertEqual(t, DefaultBackgroundPadding.Top, canvasBoxDefault.Top) testutil.AssertEqual(t, DefaultBackgroundPadding.Left, canvasBoxDefault.Left) testutil.AssertEqual(t, c.GetWidth()-DefaultBackgroundPadding.Right, canvasBoxDefault.Right) testutil.AssertEqual(t, c.GetHeight()-DefaultBackgroundPadding.Bottom, canvasBoxDefault.Bottom) custom := Chart{ Background: Style{ Padding: Box{ Top: DefaultBackgroundPadding.Top + 1, Left: DefaultBackgroundPadding.Left + 1, Right: DefaultBackgroundPadding.Right + 1, Bottom: DefaultBackgroundPadding.Bottom + 1, }, }, } canvasBoxCustom := custom.getDefaultCanvasBox() testutil.AssertFalse(t, canvasBoxCustom.IsZero()) testutil.AssertEqual(t, DefaultBackgroundPadding.Top+1, canvasBoxCustom.Top) testutil.AssertEqual(t, DefaultBackgroundPadding.Left+1, canvasBoxCustom.Left) testutil.AssertEqual(t, c.GetWidth()-(DefaultBackgroundPadding.Right+1), canvasBoxCustom.Right) testutil.AssertEqual(t, c.GetHeight()-(DefaultBackgroundPadding.Bottom+1), canvasBoxCustom.Bottom) } func TestChartGetValueFormatters(t *testing.T) { // replaced new assertions helper c := Chart{ Series: []Series{ ContinuousSeries{ XValues: []float64{-2.0, -1.0, 0, 1.0, 2.0}, YValues: []float64{1.0, 2.0, 3.0, 4.0, 4.5}, }, ContinuousSeries{ XValues: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, YValues: []float64{-2.1, -1.0, 0, 1.0, 2.0}, }, ContinuousSeries{ YAxis: YAxisSecondary, XValues: []float64{1.0, 2.0, 3.0, 4.0, 5.0}, YValues: []float64{10.0, 11.0, 12.0, 13.0, 14.0}, }, }, } dxf, dyf, dyaf := c.getValueFormatters() testutil.AssertNotNil(t, dxf) testutil.AssertNotNil(t, dyf) testutil.AssertNotNil(t, dyaf) } func TestChartHasAxes(t *testing.T) { // replaced new assertions helper testutil.AssertTrue(t, Chart{}.hasAxes()) testutil.AssertFalse(t, Chart{XAxis: XAxis{Style: Hidden()}, YAxis: YAxis{Style: Hidden()}, YAxisSecondary: YAxis{Style: Hidden()}}.hasAxes()) x := Chart{ XAxis: XAxis{ Style: Hidden(), }, YAxis: YAxis{ Style: Shown(), }, YAxisSecondary: YAxis{ Style: Hidden(), }, } testutil.AssertTrue(t, x.hasAxes()) y := Chart{ XAxis: XAxis{ Style: Shown(), }, YAxis: YAxis{ Style: Hidden(), }, YAxisSecondary: YAxis{ Style: Hidden(), }, } testutil.AssertTrue(t, y.hasAxes()) ya := Chart{ XAxis: XAxis{ Style: Hidden(), }, YAxis: YAxis{ Style: Hidden(), }, YAxisSecondary: YAxis{ Style: Shown(), }, } testutil.AssertTrue(t, ya.hasAxes()) } func TestChartGetAxesTicks(t *testing.T) { // replaced new assertions helper r, err := PNG(1024, 1024) testutil.AssertNil(t, err) c := Chart{ XAxis: XAxis{ Range: &ContinuousRange{Min: 9.8, Max: 19.8}, }, YAxis: YAxis{ Range: &ContinuousRange{Min: 9.9, Max: 19.9}, }, YAxisSecondary: YAxis{ Range: &ContinuousRange{Min: 9.7, Max: 19.7}, }, } xr, yr, yar := c.getRanges() xt, yt, yat := c.getAxesTicks(r, xr, yr, yar, FloatValueFormatter, FloatValueFormatter, FloatValueFormatter) testutil.AssertNotEmpty(t, xt) testutil.AssertNotEmpty(t, yt) testutil.AssertNotEmpty(t, yat) } func TestChartSingleSeries(t *testing.T) { // replaced new assertions helper now := time.Now() c := Chart{ Title: "Hello!", Width: 1024, Height: 400, YAxis: YAxis{ Range: &ContinuousRange{ Min: 0.0, Max: 4.0, }, }, Series: []Series{ TimeSeries{ Name: "goog", XValues: []time.Time{now.AddDate(0, 0, -3), now.AddDate(0, 0, -2), now.AddDate(0, 0, -1)}, YValues: []float64{1.0, 2.0, 3.0}, }, }, } buffer := bytes.NewBuffer([]byte{}) c.Render(PNG, buffer) testutil.AssertNotEmpty(t, buffer.Bytes()) } func TestChartRegressionBadRanges(t *testing.T) { // replaced new assertions helper c := Chart{ Series: []Series{ ContinuousSeries{ XValues: []float64{math.Inf(1), math.Inf(1), math.Inf(1), math.Inf(1), math.Inf(1)}, YValues: []float64{1.0, 2.0, 3.0, 4.0, 4.5}, }, }, } buffer := bytes.NewBuffer([]byte{}) c.Render(PNG, buffer) testutil.AssertTrue(t, true, "Render needs to finish.") } func TestChartRegressionBadRangesByUser(t *testing.T) { // replaced new assertions helper c := Chart{ YAxis: YAxis{ Range: &ContinuousRange{ Min: math.Inf(-1), Max: math.Inf(1), // this could really happen? eh. }, }, Series: []Series{ ContinuousSeries{ XValues: LinearRange(1.0, 10.0), YValues: LinearRange(1.0, 10.0), }, }, } buffer := bytes.NewBuffer([]byte{}) c.Render(PNG, buffer) testutil.AssertTrue(t, true, "Render needs to finish.") } func TestChartValidatesSeries(t *testing.T) { // replaced new assertions helper c := Chart{ Series: []Series{ ContinuousSeries{ XValues: LinearRange(1.0, 10.0), YValues: LinearRange(1.0, 10.0), }, }, } testutil.AssertNil(t, c.validateSeries()) c = Chart{ Series: []Series{ ContinuousSeries{ XValues: LinearRange(1.0, 10.0), }, }, } testutil.AssertNotNil(t, c.validateSeries()) } func TestChartCheckRanges(t *testing.T) { // replaced new assertions helper c := Chart{ Series: []Series{ ContinuousSeries{ XValues: []float64{1.0, 2.0}, YValues: []float64{3.10, 3.14}, }, }, } xr, yr, yra := c.getRanges() testutil.AssertNil(t, c.checkRanges(xr, yr, yra)) } func TestChartCheckRangesWithRanges(t *testing.T) { // replaced new assertions helper c := Chart{ XAxis: XAxis{ Range: &ContinuousRange{ Min: 0, Max: 10, }, }, YAxis: YAxis{ Range: &ContinuousRange{ Min: 0, Max: 5, }, }, Series: []Series{ ContinuousSeries{ XValues: []float64{1.0, 2.0}, YValues: []float64{3.14, 3.14}, }, }, } xr, yr, yra := c.getRanges() testutil.AssertNil(t, 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) { // replaced new assertions helper c := Chart{ Height: 50, Width: 50, TitleStyle: Hidden(), XAxis: HideXAxis(), YAxis: HideYAxis(), YAxisSecondary: HideYAxis(), Canvas: Style{ Padding: BoxZero, }, Background: Style{ Padding: BoxZero, }, Series: []Series{ ContinuousSeries{ XValues: LinearRangeWithStep(0, 4, 1), YValues: LinearRangeWithStep(0, 4, 1), }, }, } var buffer = &bytes.Buffer{} err := c.Render(PNG, buffer) testutil.AssertNil(t, err) // do color tests ... i, err := png.Decode(buffer) testutil.AssertNil(t, err) // test the bottom and top of the line testutil.AssertEqual(t, drawing.ColorWhite, at(i, 0, 0)) testutil.AssertEqual(t, drawing.ColorWhite, at(i, 49, 49)) // test a line mid point defaultSeriesColor := GetDefaultColor(0) testutil.AssertEqual(t, defaultSeriesColor, at(i, 0, 49)) testutil.AssertEqual(t, defaultSeriesColor, at(i, 49, 0)) testutil.AssertEqual(t, drawing.ColorFromHex("bddbf6"), at(i, 24, 24)) } func TestChartE2ELineWithFill(t *testing.T) { // replaced new assertions helper logBuffer := new(bytes.Buffer) c := Chart{ Height: 50, Width: 50, Canvas: Style{ Padding: BoxZero, }, Background: Style{ Padding: BoxZero, }, TitleStyle: Hidden(), XAxis: HideXAxis(), YAxis: HideYAxis(), YAxisSecondary: HideYAxis(), Series: []Series{ ContinuousSeries{ Style: Style{ StrokeColor: drawing.ColorBlue, FillColor: drawing.ColorRed, }, XValues: LinearRangeWithStep(0, 4, 1), YValues: LinearRangeWithStep(0, 4, 1), }, }, Log: NewLogger(OptLoggerStdout(logBuffer), OptLoggerStderr(logBuffer)), } testutil.AssertEqual(t, 5, len(c.Series[0].(ContinuousSeries).XValues)) testutil.AssertEqual(t, 5, len(c.Series[0].(ContinuousSeries).YValues)) var buffer = &bytes.Buffer{} err := c.Render(PNG, buffer) testutil.AssertNil(t, err) i, err := png.Decode(buffer) testutil.AssertNil(t, err) // test the bottom and top of the line testutil.AssertEqual(t, drawing.ColorWhite, at(i, 0, 0)) testutil.AssertEqual(t, drawing.ColorRed, at(i, 49, 49)) // test a line mid point defaultSeriesColor := drawing.ColorBlue testutil.AssertEqual(t, defaultSeriesColor, at(i, 0, 49)) testutil.AssertEqual(t, defaultSeriesColor, at(i, 49, 0)) } func Test_Chart_cve(t *testing.T) { poc := StackedBarChart{ Title: "poc", Bars: []StackedBar{ { Name: "11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111", Values: []Value{ {Value: 1, Label: "infinite"}, {Value: 1, Label: "loop"}, }, }, }, } var imgContent bytes.Buffer err := poc.Render(PNG, &imgContent) testutil.AssertNotNil(t, err) }