// GoCode returns the rendered Go code for the Shape. func (s *Shape) GoCode() string { code := s.Docstring() + "type " + s.ShapeName + " " switch s.Type { case "structure": code += "struct {\n" for _, n := range s.MemberNames() { m := s.MemberRefs[n] code += m.Docstring() if (m.Streaming || m.Shape.Streaming) && s.Payload == n { rtype := "io.ReadSeeker" if len(s.refs) > 1 { rtype = "aws.ReaderSeekCloser" } else if strings.HasSuffix(s.ShapeName, "Output") { rtype = "io.ReadCloser" } s.API.imports["io"] = true code += n + " " + rtype + " " + m.GoTags(false, s.IsRequired(n)) + "\n\n" } else { code += n + " " + m.GoType() + " " + m.GoTags(false, s.IsRequired(n)) + "\n\n" } } metaStruct := "metadata" + s.ShapeName ref := &ShapeRef{ShapeName: s.ShapeName, API: s.API, Shape: s} code += "\n" + metaStruct + " `json:\"-\" xml:\"-\"`\n" code += "}\n\n" code += "type " + metaStruct + " struct {\n" code += "SDKShapeTraits bool " + ref.GoTags(true, false) code += "}" default: panic("Cannot generate toplevel shape for " + s.Type) } return util.GoFmt(code) }
// APIGoCode renders the API in Go code. Returning it as a string func (a *API) APIGoCode() string { a.resetImports() a.imports["sync"] = true var buf bytes.Buffer err := tplAPI.Execute(&buf, a) if err != nil { panic(err) } code := a.importsGoCode() + strings.TrimSpace(buf.String()) return util.GoFmt(code) }
// ServiceGoCode renders service go code. Returning it as a string. func (a *API) ServiceGoCode() string { a.resetImports() a.imports["github.com/ks3sdklib/aws-sdk-go/internal/signer/v4"] = true a.imports["github.com/ks3sdklib/aws-sdk-go/internal/protocol/"+a.ProtocolPackage()] = true var buf bytes.Buffer err := tplService.Execute(&buf, a) if err != nil { panic(err) } code := a.importsGoCode() + buf.String() return util.GoFmt(code) }
func (t *testSuite) TestSuite() string { var buf bytes.Buffer t.title = reStripSpace.ReplaceAllStringFunc(t.Description, func(x string) string { return strings.ToUpper(x[1:]) }) t.title = regexp.MustCompile(`\W`).ReplaceAllString(t.title, "") for idx, c := range t.Cases { c.TestSuite = t buf.WriteString(c.TestCase(idx) + "\n") } return util.GoFmt(buf.String()) }
// InterfaceGoCode returns the go code for the service's API operations as an // interface{}. Assumes that the interface is being created in a different // package than the service API's package. func (a *API) InterfaceGoCode() string { a.resetImports() a.imports = map[string]bool{ "github.com/ks3sdklib/aws-sdk-go/service/" + a.PackageName(): true, } var buf bytes.Buffer err := tplInterface.Execute(&buf, a) if err != nil { panic(err) } code := a.importsGoCode() + strings.TrimSpace(buf.String()) return util.GoFmt(code) }
// ExampleGoCode renders service example code. Returning it as a string. func (a *API) ExampleGoCode() string { exs := []string{} for _, o := range a.OperationList() { exs = append(exs, o.Example()) } code := fmt.Sprintf("import (\n%q\n%q\n%q\n\n%q\n%q\n%q\n%q\n)\n\n"+ "var _ time.Duration\nvar _ bytes.Buffer\n\n%s", "bytes", "fmt", "time", "github.com/ks3sdklib/aws-sdk-go/aws", "github.com/ks3sdklib/aws-sdk-go/aws/awserr", "github.com/ks3sdklib/aws-sdk-go/aws/awsutil", "github.com/ks3sdklib/aws-sdk-go/service/"+a.PackageName(), strings.Join(exs, "\n\n"), ) return util.GoFmt(code) }
func main() { out := generateTestSuite(os.Args[1]) if len(os.Args) == 3 { f, err := os.Create(os.Args[2]) defer f.Close() if err != nil { panic(err) } f.WriteString(util.GoFmt(out)) f.Close() c := exec.Command("gofmt", "-s", "-w", os.Args[2]) if err := c.Run(); err != nil { panic(err) } } else { fmt.Println(out) } }
func (i *testCase) TestCase(idx int) string { var buf bytes.Buffer opName := i.TestSuite.API.StructName() + i.TestSuite.title + "Case" + strconv.Itoa(idx+1) if i.Params != nil { // input test // query test should sort body as form encoded values switch i.TestSuite.API.Metadata.Protocol { case "query", "ec2": m, _ := url.ParseQuery(i.InputTest.Body) i.InputTest.Body = m.Encode() case "rest-xml": i.InputTest.Body = util.SortXML(bytes.NewReader([]byte(i.InputTest.Body))) case "json", "rest-json": i.InputTest.Body = strings.Replace(i.InputTest.Body, " ", "", -1) } input := tplInputTestCaseData{ TestCase: i, OpName: strings.ToUpper(opName[0:1]) + opName[1:], ParamsString: helpers.ParamsStructFromJSON(i.Params, i.Given.InputRef.Shape, false), } if err := tplInputTestCase.Execute(&buf, input); err != nil { panic(err) } } else { output := tplOutputTestCaseData{ TestCase: i, Body: fmt.Sprintf("%q", i.OutputTest.Body), OpName: strings.ToUpper(opName[0:1]) + opName[1:], Assertions: utilassert.GenerateAssertions(i.Data, i.Given.OutputRef.Shape, "out"), } if err := tplOutputTestCase.Execute(&buf, output); err != nil { panic(err) } } return util.GoFmt(buf.String()) }
// generateTestSuite generates a protocol test suite for a given configuration // JSON protocol test file. func generateTestSuite(filename string) string { inout := "Input" if strings.Contains(filename, "output/") { inout = "Output" } var suites []testSuite f, err := os.Open(filename) if err != nil { panic(err) } err = json.NewDecoder(f).Decode(&suites) if err != nil { panic(err) } var buf bytes.Buffer buf.WriteString("package " + suites[0].ProtocolPackage() + "_test\n\n") var innerBuf bytes.Buffer innerBuf.WriteString("//\n// Tests begin here\n//\n\n\n") for i, suite := range suites { svcPrefix := inout + "Service" + strconv.Itoa(i+1) suite.API.Metadata.ServiceAbbreviation = svcPrefix + "ProtocolTest" suite.API.Operations = map[string]*api.Operation{} for idx, c := range suite.Cases { c.Given.ExportedName = svcPrefix + "TestCaseOperation" + strconv.Itoa(idx+1) suite.API.Operations[c.Given.ExportedName] = c.Given } suite.API.NoInflections = true // don't require inflections suite.API.NoInitMethods = true // don't generate init methods suite.API.Setup() suite.API.Metadata.EndpointPrefix = suite.API.PackageName() // Sort in order for deterministic test generation names := make([]string, 0, len(suite.API.Shapes)) for n := range suite.API.Shapes { names = append(names, n) } sort.Strings(names) for _, name := range names { s := suite.API.Shapes[name] s.Rename(svcPrefix + "TestShape" + name) } svcCode := addImports(suite.API.ServiceGoCode()) if i == 0 { importMatch := reImportRemoval.FindStringSubmatch(svcCode) buf.WriteString(importMatch[0] + "\n\n") buf.WriteString(preamble + "\n\n") } svcCode = removeImports(svcCode) svcCode = strings.Replace(svcCode, "func New(", "func New"+suite.API.StructName()+"(", -1) buf.WriteString(svcCode + "\n\n") apiCode := removeImports(suite.API.APIGoCode()) apiCode = strings.Replace(apiCode, "var oprw sync.Mutex", "", -1) apiCode = strings.Replace(apiCode, "oprw.Lock()", "", -1) apiCode = strings.Replace(apiCode, "defer oprw.Unlock()", "", -1) buf.WriteString(apiCode + "\n\n") innerBuf.WriteString(suite.TestSuite() + "\n") } return util.GoFmt(buf.String() + innerBuf.String()) }
func writeGoFile(file string, layout string, args ...interface{}) error { return ioutil.WriteFile(file, []byte(util.GoFmt(fmt.Sprintf(layout, args...))), 0664) }
// ParamsStructFromJSON returns a JSON string representation of a structure. func ParamsStructFromJSON(value interface{}, shape *api.Shape, prefixPackageName bool) string { f := paramFiller{prefixPackageName: prefixPackageName} return util.GoFmt(f.paramsStructAny(value, shape)) }