Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion mdl/executor/roundtrip_doctype_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,18 +552,37 @@ func parseMajorMinor(s string) (int, int, bool) {
func filterByVersion(content string, pv *types.ProjectVersion) (string, int) {
var result strings.Builder
var currentConstraint *versionConstraint // nil = no constraint (always include)
// A directive placed before any statement is the FILE's floor, and later
// directives narrow it rather than replace it. Without this, `-- @version:
// any` resets the constraint to nil and re-enables a section whose fixtures
// were skipped: 24-workflow-examples.mdl opens at 11.0+, creates
// WFTest.OrderContext and WFTest.TaskPage (a page with parameters, 11.0+
// only -- mendixlabs/mxcli#294), and its PART H says `any` while using both.
// On the nightly's 10.24 leg that ran PART H against a project missing them:
// "entity 'WFTest.OrderContext' not found". Only that file has a line-1
// directive; the other six use `any` mid-file to close a gated section,
// where there is no baseline and nothing changes.
var baseline *versionConstraint
sawStatement := false
skippedLines := 0

for _, line := range strings.Split(content, "\n") {
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "-- @version:") {
currentConstraint = parseVersionDirective(trimmed)
if !sawStatement && baseline == nil {
baseline = currentConstraint
}
// Keep the directive line as a comment (so line numbers stay close)
result.WriteString(line)
result.WriteString("\n")
continue
}
if currentConstraint == nil || currentConstraint.matches(pv) {
if trimmed != "" && !strings.HasPrefix(trimmed, "--") {
sawStatement = true
}
if (baseline == nil || baseline.matches(pv)) &&
(currentConstraint == nil || currentConstraint.matches(pv)) {
result.WriteString(line)
result.WriteString("\n")
} else {
Expand Down
8 changes: 8 additions & 0 deletions mdl/executor/roundtrip_workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ import (
// page's signature and refused them, so the fixture is a valid task page.
func createTaskPages(t *testing.T, env *testEnv, mod string, names ...string) {
t.Helper()
// A user task's page must take $WorkflowUserTask or exec refuses it (CE7410
// on 11.13, which is why db61b949 added the parameter), and CREATE PAGE
// cannot write a parameter below 11.0 (mendixlabs/mxcli#294). The two
// requirements are mutually exclusive, so these fixtures cannot exist on
// Mendix 10 at all -- the nightly's 10.24 leg failed here for two days.
// The gate lives with the fixture rather than at the four call sites so a
// fifth caller cannot forget it.
env.requireMinVersion(t, 11, 0)
for _, name := range names {
mdl := `create page ` + mod + `.` + name + ` (
Title: '` + name + `',
Expand Down
74 changes: 74 additions & 0 deletions mdl/executor/version_filter_baseline_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: Apache-2.0

//go:build integration

package executor

import (
"strings"
"testing"

"github.com/mendixlabs/mxcli/mdl/types"
)

// A file-level `-- @version:` floor must survive a later `-- @version: any`.
// Without that, PART H of 24-workflow-examples.mdl ran on the nightly's Mendix
// 10.24 leg against a project whose fixtures had been skipped, and failed with
// "entity 'WFTest.OrderContext' not found for parameter 'OrderContext'".
func TestFilterByVersion_FileBaselineSurvivesAny(t *testing.T) {
const script = `-- @version: 11.0+
create persistent entity WFTest.OrderContext ( Name: string )
/
-- @version: any
create workflow WFTest.CompletionRules parameter $OrderContext: WFTest.OrderContext
/
`
mx10 := &types.ProjectVersion{ProductVersion: "10.24.24.119349", MajorVersion: 10, MinorVersion: 24}
mx11 := &types.ProjectVersion{ProductVersion: "11.13.0", MajorVersion: 11, MinorVersion: 13}

got10, skipped10 := filterByVersion(script, mx10)
if strings.Contains(got10, "create workflow") {
t.Errorf("Mendix 10: the `any` section ran although the file floor is 11.0+ "+
"and its fixtures were skipped.\nfiltered:\n%s", got10)
}
if strings.Contains(got10, "create persistent entity") {
t.Errorf("Mendix 10: the gated fixture should have been skipped too")
}
if skipped10 == 0 {
t.Errorf("Mendix 10: expected skipped lines, got 0")
}

got11, _ := filterByVersion(script, mx11)
for _, want := range []string{"create persistent entity", "create workflow"} {
if !strings.Contains(got11, want) {
t.Errorf("Mendix 11: %q was dropped; the floor is satisfied so everything must run.\n%s", want, got11)
}
}
}

// The other six fixtures use `any` MID-file to close a gated section. There is
// no baseline there, so the section must still run on every version -- the
// control that keeps the fix above from over-firing.
func TestFilterByVersion_MidFileAnyStillReopens(t *testing.T) {
const script = `create entity M.Always ( Name: string )
/
-- @version: 10.18+
create view entity M.Gated ( Name: string )
/
-- @version: any
create entity M.AfterAny ( Name: string )
/
`
mx10 := &types.ProjectVersion{ProductVersion: "10.6.0", MajorVersion: 10, MinorVersion: 6}

got, _ := filterByVersion(script, mx10)
if !strings.Contains(got, "M.AfterAny") {
t.Errorf("a mid-file `any` must reopen for every version:\n%s", got)
}
if strings.Contains(got, "M.Gated") {
t.Errorf("the 10.18+ section must still be skipped on 10.6:\n%s", got)
}
if !strings.Contains(got, "M.Always") {
t.Errorf("content before any directive must always run:\n%s", got)
}
}
Loading