This is an automated email from the ASF dual-hosted git repository.

sjanc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newt.git

commit cf8bb25209b011177dc9d39ef7142fb8eac535b2
Author: Szymon Janc <[email protected]>
AuthorDate: Thu Oct 15 18:03:03 2026 +0200

    newt/sysinit: Fix panic if no function has a stage number
    
    ResolveStageFuncsOrder() always used the first stage number when adding
    implicit dependencies between stages. If no function had a stage number,
    e.g. all used $before or $after or there were no functions at all, it
    panicked with index out of range.
    
    Add unit tests for ResolveStageFuncsOrder().
    
    Assisted-by: Claude:claude-opus-5-5
---
 newt/sysinit/sysinit.go      |  3 +-
 newt/sysinit/sysinit_test.go | 84 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 2 deletions(-)

diff --git a/newt/sysinit/sysinit.go b/newt/sysinit/sysinit.go
index 9c3a1457..9747e90b 100644
--- a/newt/sysinit/sysinit.go
+++ b/newt/sysinit/sysinit.go
@@ -181,8 +181,7 @@ func ResolveStageFuncsOrder(sfs []stage.StageFunc) 
([]stage.StageFunc, error) {
        // direct dependencies between each node of stage X to each node of
        // stage Y to make sure they can be resolved properly and reordered
        // if needed due to other dependencies.
-       sfsPrev := nodesByStage[stages[0]]
-       stages = stages[1:]
+       var sfsPrev []*stage.StageFunc
        for _, stage := range stages {
                sfsCurr := nodesByStage[stage]
 
diff --git a/newt/sysinit/sysinit_test.go b/newt/sysinit/sysinit_test.go
new file mode 100644
index 00000000..9a99a748
--- /dev/null
+++ b/newt/sysinit/sysinit_test.go
@@ -0,0 +1,84 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 sysinit
+
+import (
+       "slices"
+       "testing"
+
+       "mynewt.apache.org/newt/newt/stage"
+       "mynewt.apache.org/newt/newt/val"
+)
+
+func stagedFunc(name string, stg string) stage.StageFunc {
+       return stage.StageFunc{
+               Name:  name,
+               Stage: val.ValSetting{Text: stg, Value: stg},
+       }
+}
+
+func checkOrder(t *testing.T, sfs []stage.StageFunc, expected []string) {
+       t.Helper()
+
+       sorted, err := ResolveStageFuncsOrder(sfs)
+       if err != nil {
+               t.Fatal(err)
+       }
+
+       names := []string{}
+       for _, sf := range sorted {
+               names = append(names, sf.Name)
+       }
+
+       if !slices.Equal(names, expected) {
+               t.Errorf("unexpected order: got %v, expected %v", names, 
expected)
+       }
+}
+
+func TestResolveStageFuncsOrderEmpty(t *testing.T) {
+       checkOrder(t, nil, []string{})
+}
+
+func TestResolveStageFuncsOrderNoStages(t *testing.T) {
+       a := stage.StageFunc{Name: "a"}
+       a.Stage.Afters = []string{"b"}
+       b := stage.StageFunc{Name: "b"}
+
+       checkOrder(t, []stage.StageFunc{a, b}, []string{"b", "a"})
+}
+
+func TestResolveStageFuncsOrderStages(t *testing.T) {
+       checkOrder(t, []stage.StageFunc{
+               stagedFunc("c", "200"),
+               stagedFunc("b", "100"),
+               stagedFunc("a", "100"),
+       }, []string{"a", "b", "c"})
+}
+
+func TestResolveStageFuncsOrderMixed(t *testing.T) {
+       d := stage.StageFunc{Name: "d"}
+       d.Stage.Befores = []string{"b"}
+
+       checkOrder(t, []stage.StageFunc{
+               stagedFunc("b", "200"),
+               stagedFunc("a", "100"),
+               d,
+       }, []string{"a", "d", "b"})
+}

Reply via email to