From 79609ce4fbded86efe601c1cf42afab146e45ac8 Mon Sep 17 00:00:00 2001 From: Vector7 <39830125+wjsvec@users.noreply.github.com> Date: Thu, 10 Aug 2023 18:35:45 +0800 Subject: [PATCH] feat: support to generate a PDF report #162 --- .gitignore | 1 + cmd/data/font/.keep | 0 cmd/data/image/warn.jpg | Bin 0 -> 1316 bytes cmd/run.go | 2 + go.mod | 4 ++ go.sum | 8 ++++ pkg/runner/writer_pdf.go | 97 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 112 insertions(+) create mode 100644 cmd/data/font/.keep create mode 100644 cmd/data/image/warn.jpg create mode 100644 pkg/runner/writer_pdf.go diff --git a/.gitignore b/.gitignore index 83ba05bf..f41bb2e1 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ cmd/data/index.html cmd/data/index.js cmd/data/index.css operator/bundle +oryxbuildbinary \ No newline at end of file diff --git a/cmd/data/font/.keep b/cmd/data/font/.keep new file mode 100644 index 00000000..e69de29b diff --git a/cmd/data/image/warn.jpg b/cmd/data/image/warn.jpg new file mode 100644 index 0000000000000000000000000000000000000000..674518d283d729390e2f8cd50573c62174a85cfb GIT binary patch literal 1316 zcmex=TVf!H8JK-xjNfQW~KodcwTH1PibgCGZk5`!W$qY?v? zAS1IN6#zP)nVAXbSXLGmpz2znJOhg$ ztB|6hBb#twBD+$dh*9Ijg&fLG8xM*GUHqV8oK)1r$t5N(At|M*rmmr>WnyY(ZeeNV z?BeR??&0Yb91<+v*#~fzWVs- z^OvvRzW@073*;|G24;x2;66k1mmttzOu#r`VF&q(k*OSrnFU!`6%E;h90S=C3x$=8 z8aYIqCNA7~kW<+>=!0ld(M2vX6_bamA3CdPC8CWm;UA*-_15@3x{|rK= z`#G|%OSvt4xZ6W_&HCIELN1@~Ir5xq-<(?(aCl;a8*fdybo%7e9|9M*P3o<2S?o3U zmsj4MdlUWsZHx6!S2?i8wcM)f!?HO`Uu@leKKb4H)_GR(9d-guU*1MfwF^C^?>eFM z_(lok*Ris7RsR_d^44eC3)DFO?YEP8z0crk+SRS{!cph*t1HczPpgDaJ}lDPz?i#Y zm4D5o%JmmkS*Y90OKhAf<1=}E`;?U-+an!s&%WdxyM5OS$$PAcuUB3UTOO$Ce(`nw zw1ci9;Wy?Pp8S*c@%|r$d0g`%Zs)$e{!VwVv*79a18)A;<+lDj5A?dz57$TX{q`Hm zkN9&}MEg$;yZ+VMyL{^wx6tZl(L2IM>mD)YPTa;;X(8)d+yC3aeeI9M$Nhy~?rM&_ zq0x6|3D2pY44a$SEN$u!xYqpr9aneq)_;b#?!PT6Rv$3?9`(I-*+iowU?{t@j8BWP~xXRUahv(AMDo@R(tq;9+`rlXSbx~wl_T$U{mW_Z_FY@b z!>WsQ?_Ac}807YLlAc?IrR?f2@ej`T?SE+fAw<~Y_WIoV!s1sEeA53|4C;1%S>OGi zA*KGNbKKwQ`_uKgesDc{9rw}ap7gftvMcY_Ea`n$?)51_FFI>QZP)HTQIYhnU(Da? z`lCPW@0+A{xs-MDerMT(6_TL_oZ%`x1r`4p8l^0R?T;l?Y+LK;7PPc;rK;LOmH8&K zdoES2jXNJI_I^eB4KCA9Gme@p_tIP&T%{ZO*Y4ZI_frC0>m%k*W)%r^fMNOnHvz83 BA4C8E literal 0 HcmV?d00001 diff --git a/cmd/run.go b/cmd/run.go index 089d0a93..62f00982 100644 --- a/cmd/run.go +++ b/cmd/run.go @@ -110,6 +110,8 @@ func (o *runOption) preRunE(cmd *cobra.Command, args []string) (err error) { o.reportWriter = runner.NewDiscardResultWriter() case "", "std": o.reportWriter = runner.NewResultWriter(writer) + case "pdf": + o.reportWriter = runner.NewPDFResultWriter(writer) default: err = fmt.Errorf("not supported report type: '%s'", o.report) } diff --git a/go.mod b/go.mod index 6811796a..4be47b60 100644 --- a/go.mod +++ b/go.mod @@ -29,6 +29,7 @@ require ( github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect github.com/cucumber/messages-go/v16 v16.0.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/flopp/go-findfont v0.1.0 // indirect github.com/gofrs/uuid v4.2.0+incompatible // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.0 // indirect @@ -43,10 +44,13 @@ require ( github.com/kr/text v0.2.0 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/reflectwalk v1.0.0 // indirect + github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 // indirect + github.com/pkg/errors v0.8.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect github.com/shopspring/decimal v1.2.0 // indirect + github.com/signintech/gopdf v0.18.0 // indirect github.com/spf13/cast v1.3.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tidwall/match v1.1.1 // indirect diff --git a/go.sum b/go.sum index a26a5e06..f5340c80 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ github.com/cucumber/messages-go/v16 v16.0.1/go.mod h1:EJcyR5Mm5ZuDsKJnT2N9KRnBK3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/flopp/go-findfont v0.1.0 h1:lPn0BymDUtJo+ZkV01VS3661HL6F4qFlkhcJN55u6mU= +github.com/flopp/go-findfont v0.1.0/go.mod h1:wKKxRDjD024Rh7VMwoU90i6ikQRCr+JTHB5n4Ejkqvw= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -84,6 +86,10 @@ github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/I github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4= github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms= +github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311 h1:zyWXQ6vu27ETMpYsEMAsisQ+GqJ4e1TPvSNfdOPF0no= +github.com/phpdave11/gofpdi v1.0.14-0.20211212211723-1f10f9844311/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= @@ -93,6 +99,8 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/signintech/gopdf v0.18.0 h1:ktQSrhoeQSImPBIIH9Z3vnTJZXCfiGYzgYW2Vy5Ff+c= +github.com/signintech/gopdf v0.18.0/go.mod h1:wrLtZoWaRNrS4hphED0oflFoa6IWkOu6M3nJjm4VbO4= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= diff --git a/pkg/runner/writer_pdf.go b/pkg/runner/writer_pdf.go new file mode 100644 index 00000000..2302c6d7 --- /dev/null +++ b/pkg/runner/writer_pdf.go @@ -0,0 +1,97 @@ +package runner + +import ( + _ "embed" + + "fmt" + "github.com/linuxsuren/api-testing/pkg/apispec" + "io" + "github.com/signintech/gopdf" + "github.com/flopp/go-findfont" + "log" + "strconv" +) + +type pdfResultWriter struct { + writer io.Writer +} + +// NewPDFResultWriter creates a new PDFResultWriter +func NewPDFResultWriter(writer io.Writer) ReportResultWriter { + return &pdfResultWriter{writer: writer} +} + +// Output writes the PDF base report to target writer +func (w *pdfResultWriter) Output(result []ReportResult) (err error) { + + + pdf := gopdf.GoPdf{} + pdf.Start(gopdf.Config{PageSize: *gopdf.PageSizeA4}) + fmt.Println(findfont.List()[len(findfont.List())-1]) + fontPath, err := findfont.Find("DejaVuSerif.ttf") + if err != nil { + panic(err) + } + fmt.Printf("Found 'ttf' in '%s'\n", fontPath) + err = pdf.AddTTFFont("wts11", fontPath) + if err != nil { + log.Print(err.Error()) + return + } + err = pdf.SetFont("wts11", "", 14) + if err != nil { + log.Print(err.Error()) + return + } + + pdf.AddHeader(func() { + + }) + pdf.AddFooter(func() { + const X_bias float64 = 101 + pdf.SetXY(X_bias, 825) + + pdf.Text("Generated by github.com/LinuxSuRen/api-testing") + pdf.AddExternalLink("https://github.com/LinuxSuRen/api-testing", 95+X_bias, 813, 200, 15) + + // pdf.Image("../pkg/runner/data/imgs/gopher.jpg", 500, 780, nil) //print image + }) + + const line_bias float64 = 50 + const Y_start float64 = 100 + for _, api := range result { + pdf.AddPage() + pdf.SetXY(50, Y_start) + pdf.Cell(nil, "API: "+string(api.API)) + pdf.SetXY(50, Y_start+line_bias) + pdf.Cell(nil, "Count: "+strconv.Itoa(api.Count)) + pdf.SetXY(50, Y_start+line_bias*2) + pdf.Cell(nil, "Average:"+api.Average.String()) + pdf.SetXY(50, Y_start+line_bias*3) + pdf.Cell(nil, "Max: "+api.Max.String()) + pdf.SetXY(50, Y_start+line_bias*4) + pdf.Cell(nil, "Min: "+api.Min.String()) + pdf.SetXY(50, Y_start+line_bias*5) + pdf.Cell(nil, "QPS: "+strconv.Itoa(api.QPS)) + pdf.SetXY(50, Y_start+line_bias*6) + pdf.Cell(nil, "Error: "+strconv.Itoa(api.Error)) + pdf.SetXY(50, Y_start+line_bias*7) + pdf.Cell(nil, "LastErrorMessage:") + pdf.SetXY(50, Y_start+line_bias*8) + pdf.Cell(nil, api.LastErrorMessage) + + if api.Error != 0 { + pdf.Image("../pkg/runner/data/imgs/warn.jpg", 30, Y_start+line_bias*6-5, nil) + } + + } + + fmt.Fprint(w.writer, "Report is OK!") + pdf.WritePdf("Report.pdf") + return +} + +// WithAPIConverage sets the api coverage +func (w *pdfResultWriter) WithAPIConverage(apiConverage apispec.APIConverage) ReportResultWriter { + return w +}