151 lines
4.7 KiB
Go
151 lines
4.7 KiB
Go
// Copyright 2024 Dolthub, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/cockroachdb/errors"
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
"golang.org/x/text/cases"
|
|
"golang.org/x/text/language"
|
|
|
|
"github.com/dolthub/doltgresql/testing/generation/utils"
|
|
)
|
|
|
|
const TestHeader = `// Copyright %d Dolthub, Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package output
|
|
|
|
import (
|
|
"testing"
|
|
"github.com/dolthub/go-mysql-server/sql"
|
|
)
|
|
|
|
func Test_%s(t *testing.T) {
|
|
RunScripts(t, []ScriptTest{
|
|
`
|
|
|
|
const TestFooter = ` })
|
|
}
|
|
`
|
|
|
|
// GenerateTests generates and writes a test file for the given function.
|
|
func GenerateTests(parentFolder utils.RootFolderLocation, functionName string, assertions []Assertion) error {
|
|
// We want to skip some functions since we know they'll always return a different result
|
|
switch functionName {
|
|
case "random":
|
|
return nil
|
|
}
|
|
// For now we'll skip some functions that will take a long time to calculate
|
|
switch functionName {
|
|
case "exp", "factorial", "lpad", "power", "rpad", "repeat", "round":
|
|
return nil
|
|
}
|
|
|
|
sb := strings.Builder{}
|
|
sb.WriteString(fmt.Sprintf(TestHeader, time.Now().Year(),
|
|
strings.ReplaceAll(cases.Title(language.English).String(strings.ReplaceAll(functionName, "_", " ")), " ", "")))
|
|
sb.WriteString("\t\t{\n")
|
|
sb.WriteString(fmt.Sprintf("\t\t\tName: \"%s\",\n", functionName))
|
|
sb.WriteString("\t\t\tAssertions: []ScriptTestAssertion{\n")
|
|
for _, assertion := range assertions {
|
|
sb.WriteString("\t\t\t\t{\n")
|
|
if !assertion.Error {
|
|
sb.WriteString(fmt.Sprintf("\t\t\t\t\tQuery: \"%s\",\n", assertion.Stmt))
|
|
sb.WriteString("\t\t\t\t\tExpected: []sql.Row{")
|
|
for i, results := range assertion.Rows {
|
|
if i > 0 {
|
|
sb.WriteRune(',')
|
|
}
|
|
sb.WriteRune('{')
|
|
for j, result := range results {
|
|
if j > 0 {
|
|
sb.WriteRune(',')
|
|
}
|
|
switch result := result.(type) {
|
|
case int:
|
|
sb.WriteString(fmt.Sprintf("int64(%d)", result))
|
|
case int8:
|
|
sb.WriteString(fmt.Sprintf("int8(%d)", result))
|
|
case int16:
|
|
sb.WriteString(fmt.Sprintf("int16(%d)", result))
|
|
case int32:
|
|
sb.WriteString(fmt.Sprintf("int32(%d)", result))
|
|
case int64:
|
|
sb.WriteString(fmt.Sprintf("int64(%d)", result))
|
|
case uint:
|
|
sb.WriteString(fmt.Sprintf("uint64(%d)", result))
|
|
case uint8:
|
|
sb.WriteString(fmt.Sprintf("uint8(%d)", result))
|
|
case uint16:
|
|
sb.WriteString(fmt.Sprintf("uint16(%d)", result))
|
|
case uint32:
|
|
sb.WriteString(fmt.Sprintf("uint32(%d)", result))
|
|
case uint64:
|
|
sb.WriteString(fmt.Sprintf("uint64(%d)", result))
|
|
case float32:
|
|
sb.WriteString(fmt.Sprintf("float32(%f)", result))
|
|
case float64:
|
|
sb.WriteString(fmt.Sprintf("float64(%f)", result))
|
|
case string:
|
|
sb.WriteString(fmt.Sprintf("%q", result))
|
|
case pgtype.Numeric:
|
|
sb.WriteString(fmt.Sprintf(`Numeric("%s")`, NumericToString(result)))
|
|
case nil:
|
|
sb.WriteString("nil")
|
|
default:
|
|
return errors.Errorf("%T does not have a switch case", result)
|
|
}
|
|
}
|
|
sb.WriteRune('}')
|
|
}
|
|
sb.WriteString("},\n")
|
|
} else {
|
|
sb.WriteString(fmt.Sprintf("\t\t\t\t\tQuery: \"%s\",\n", assertion.Stmt))
|
|
sb.WriteString("\t\t\t\t\tExpectedErr: true,\n")
|
|
}
|
|
sb.WriteString("\t\t\t\t},\n")
|
|
}
|
|
sb.WriteString("\t\t\t},\n")
|
|
sb.WriteString("\t\t},\n")
|
|
sb.WriteString(TestFooter)
|
|
outputFileName := strings.ToLower(strings.ReplaceAll(functionName, " ", "_"))
|
|
return parentFolder.WriteFileToDirectory("output", outputFileName+"_test.go", []byte(sb.String()), 0644)
|
|
}
|
|
|
|
// NumericToString converts a numeric to a string.
|
|
func NumericToString(numeric pgtype.Numeric) string {
|
|
str, err := numeric.Value()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return str.(string)
|
|
}
|