feat: add optional GORM pool and SQL logging adapter
This commit is contained in:
48
scripts/testdata/gormGenerated_test.go
vendored
Normal file
48
scripts/testdata/gormGenerated_test.go
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"example.com/mysqlAcceptance/internal/config"
|
||||
"example.com/mysqlAcceptance/internal/svc"
|
||||
"git.yuntuo.hk/k2safe/go-omni/logx"
|
||||
)
|
||||
|
||||
func TestGeneratedOptionalGORM(t *testing.T) {
|
||||
cfg, err := config.Load("etc/config.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
logger, err := logx.New(logx.Config{Writer: io.Discard})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer logger.Close()
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
defer cancel()
|
||||
c, err := svc.New(ctx, logger, cfg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer c.Close()
|
||||
if c.ORM == nil {
|
||||
t.Fatal("svc.Init did not provide GORM")
|
||||
}
|
||||
pool, err := c.ORM.DB()
|
||||
if err != nil || pool != c.DB.DB {
|
||||
t.Fatal("GORM created another pool", err)
|
||||
}
|
||||
var value int
|
||||
if err = c.ORM.WithContext(ctx).Raw("SELECT ?", 42).Scan(&value).Error; err != nil || value != 42 {
|
||||
t.Fatal(value, err)
|
||||
}
|
||||
if err = c.Finish(nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err = c.ORM.WithContext(ctx).Raw("SELECT 1").Scan(&value).Error; err == nil {
|
||||
t.Fatal("ORM did not follow owner shutdown")
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ def main():
|
||||
source.add_argument("--version")
|
||||
parser.add_argument("--report", type=Path, required=True)
|
||||
parser.add_argument("--image", default="mysql:8.4")
|
||||
parser.add_argument("--gorm", action="store_true", help="also verify the optional GORM adapter and generated svc extension")
|
||||
args = parser.parse_args()
|
||||
if args.version and not re.fullmatch(r"v\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?", args.version):
|
||||
parser.error("a fixed release version is required")
|
||||
@@ -70,13 +71,16 @@ def main():
|
||||
path.chmod(0o644) # Disposable fixtures, readable by the container's mysql uid.
|
||||
project = temp / "consumer"
|
||||
project.mkdir()
|
||||
version = args.version or "v0.14.0-preview"
|
||||
version = args.version or "v0.14.1-preview"
|
||||
(project / "go.mod").write_text(f"module example.com/connectorAcceptance\n\ngo 1.22.0\n\nrequire {MODULE} {version}\n")
|
||||
if args.local:
|
||||
run(["go", "mod", "edit", f"-replace={MODULE}={ROOT}"], project, env)
|
||||
else:
|
||||
env["GOMODCACHE"] = str(temp / "modcache")
|
||||
for name in SOURCES:
|
||||
sources = list(SOURCES)
|
||||
if args.gorm:
|
||||
sources.append("database/gormx/integration_test.go")
|
||||
for name in sources:
|
||||
target = project / name
|
||||
target.parent.mkdir(exist_ok=True, parents=True)
|
||||
shutil.copyfile(ROOT / name, target)
|
||||
@@ -98,6 +102,18 @@ def main():
|
||||
command += ["--framework-dir", ROOT]
|
||||
run([*command, generated], temp, env)
|
||||
shutil.copyfile(ROOT / "scripts/testdata/mysqlGenerated_test.go", generated / "mysql_test.go")
|
||||
if args.gorm:
|
||||
# Only the documented project-owned extension is customized.
|
||||
service = generated / "internal/svc/serviceContext.go"
|
||||
code = service.read_text()
|
||||
assert '"context"' in code and 'type ServiceContext struct {' in code
|
||||
code = code.replace('"context"', '"context"\n "gorm.io/gorm"\n "' + MODULE + '/database/gormx"', 1)
|
||||
code = code.replace('type ServiceContext struct {', 'type ServiceContext struct {\n ORM *gorm.DB', 1)
|
||||
assert 'return nil' in code
|
||||
code = code.replace('return nil', 'var err error\n c.ORM, err = gormx.MySQL(ctx, c.DB, gormx.WithLogger(c.Logger))\n return err', 1)
|
||||
service.write_text(code)
|
||||
run(["gofmt", "-w", service], generated, env)
|
||||
shutil.copyfile(ROOT / "scripts/testdata/gormGenerated_test.go", generated / "gorm_test.go")
|
||||
run(["go", "mod", "tidy"], generated, env)
|
||||
generated_module = json.loads(run(["go", "list", "-m", "-json", MODULE], generated, env))
|
||||
if not args.local:
|
||||
@@ -137,6 +153,8 @@ def main():
|
||||
passed = [e["Test"] for e in events if e.get("Action") == "pass" and "Test" in e]
|
||||
assert "TestMySQLConnectorTLSAndPoolIsolation" in passed
|
||||
assert "TestStructuredMySQLAdapterTLS" in passed
|
||||
if args.gorm:
|
||||
assert "TestGORMMySQLTransactionsCancellationAndLogs" in passed
|
||||
assert not any(e.get("Action") in ("fail", "skip") for e in events), output
|
||||
env.update(GO_OMNI_DB_HOST="127.0.0.1", GO_OMNI_DB_PORT=addr.rsplit(":", 1)[1],
|
||||
GO_OMNI_DB_USER="omni_test", GO_OMNI_DB_PASSWORD=env["MYSQL_PASSWORD"],
|
||||
@@ -144,23 +162,30 @@ def main():
|
||||
GO_OMNI_DB_TLS_SERVER_NAME="localhost", GO_OMNI_DB_POOL_MAX_OPEN_CONNS="2",
|
||||
GO_OMNI_DB_POOL_MAX_IDLE_CONNS="2")
|
||||
print("Testing generated MySQL service config, independent pools and cleanup", flush=True)
|
||||
run([cli, "api", "generate", "--check"], generated, env)
|
||||
check_output = run([cli, "api", "generate", "--check"], generated, env)
|
||||
if not args.local:
|
||||
assert "frameworkVersion" not in check_output, check_output
|
||||
output = run(["go", "test", "-race", "-count=1", "-json", "-timeout=60s", "./..."], generated, env)
|
||||
generated_events = [json.loads(line) for line in output.splitlines() if line.startswith("{")]
|
||||
generated_passed = [e["Test"] for e in generated_events if e.get("Action") == "pass" and "Test" in e]
|
||||
assert "TestGeneratedMySQLConfigurationAndLifecycle" in generated_passed, output
|
||||
if args.gorm:
|
||||
assert "TestGeneratedOptionalGORM" in generated_passed, output
|
||||
assert not any(e.get("Action") == "fail" or (e.get("Action") == "skip" and "Test" in e) for e in generated_events), output
|
||||
passed += generated_passed
|
||||
image = run(["docker", "inspect", "--format", "{{.Image}}", name], temp, env).strip()
|
||||
finally:
|
||||
if created:
|
||||
run(["docker", "rm", "--force", "--volumes", name], temp, env)
|
||||
report = {"passed": True, "frameworkVersion": version, "localSource": args.local,
|
||||
report_sources = sources + ["scripts/verifyConnector.py", "scripts/testdata/mysqlGenerated_test.go"]
|
||||
if args.gorm:
|
||||
report_sources += ["scripts/testdata/gormGenerated_test.go", "database/gormx/gorm.go", "database/gormx/pool.go", "database/gormx/logger.go"]
|
||||
report = {"passed": True, "frameworkVersion": version, "localSource": args.local, "gormAdapter": args.gorm,
|
||||
"frameworkSum": module.get("Sum"), "freshModuleCache": not args.local,
|
||||
"noLocalReplace": not bool(module.get("Replace")), "mysqlImage": image,
|
||||
"mysqlLimits": {"cpus": 1, "memoryMiB": 768, "pids": 128},
|
||||
"durationSeconds": round(time.monotonic() - began, 2), "tests": passed,
|
||||
"sourceHashes": {name: hashlib.sha256((ROOT / name).read_bytes()).hexdigest() for name in (*SOURCES, "scripts/verifyConnector.py", "scripts/testdata/mysqlGenerated_test.go")}}
|
||||
"sourceHashes": {name: hashlib.sha256((ROOT / name).read_bytes()).hexdigest() for name in report_sources}}
|
||||
args.report.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.report.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n")
|
||||
print("PASS; isolated container, credentials, certificates and consumer removed", flush=True)
|
||||
|
||||
Reference in New Issue
Block a user