You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/12/08 07:31:37 UTC

incubator-mynewt-newt git commit: MYNEWT-245 Allow debug of unittest via "newt run"

Repository: incubator-mynewt-newt
Updated Branches:
  refs/heads/develop 6f1a11a8f -> 199ecc0c7


MYNEWT-245 Allow debug of unittest via "newt run"

The command is:
    newt run <unittest-pkg>

This builds the test executable such that a failed test triggers a
failed assert and runs it in gdb.  When a test fails, gdb halts at the
point of failure.

This change requires a sibling change to be made to the core repo.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/commit/199ecc0c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/tree/199ecc0c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/diff/199ecc0c

Branch: refs/heads/develop
Commit: 199ecc0c7d1a2beb2152f2d6877cc43b76b59314
Parents: 6f1a11a
Author: Christopher Collins <cc...@apache.org>
Authored: Thu Dec 8 01:26:29 2016 -0600
Committer: Christopher Collins <cc...@apache.org>
Committed: Thu Dec 8 01:26:29 2016 -0600

----------------------------------------------------------------------
 newt/builder/build.go       | 24 +++++++++----
 newt/builder/buildutil.go   |  4 ---
 newt/builder/load.go        | 32 ++++++++++++++---
 newt/builder/paths.go       |  4 +++
 newt/builder/targetbuild.go | 30 +++++++++++++++-
 newt/cli/build_cmds.go      |  4 +--
 newt/cli/run_cmds.go        | 74 ++++++++++++++++++++++------------------
 newt/cli/target_cmds.go     | 41 +++-------------------
 newt/cli/util.go            | 42 +++++++++++++++++++++++
 newt/syscfg/syscfg.go       | 18 ++++++++--
 10 files changed, 181 insertions(+), 92 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/builder/build.go
----------------------------------------------------------------------
diff --git a/newt/builder/build.go b/newt/builder/build.go
index 6114fd4..fae8d66 100644
--- a/newt/builder/build.go
+++ b/newt/builder/build.go
@@ -517,29 +517,39 @@ func (b *Builder) testOwner(p *BuildPackage) *BuildPackage {
 	}
 }
 
-func (b *Builder) Test(p *pkg.LocalPackage) error {
+// @return string               Path of generated test executable.
+func (b *Builder) BuildTest(p *pkg.LocalPackage) (string, error) {
 	// Build the packages alphabetically to ensure a consistent order.
 	bpkgs := b.sortedBuildPackages()
 	for _, bpkg := range bpkgs {
 		if err := b.buildPackage(bpkg); err != nil {
-			return err
+			return "", err
 		}
 	}
 
 	testBpkg := b.PkgMap[p]
-	testFilename := b.TestExePath(testBpkg)
-	if err := b.link(testFilename, nil, nil); err != nil {
+	testPath := b.TestExePath(testBpkg)
+	if err := b.link(testPath, nil, nil); err != nil {
+		return "", err
+	}
+
+	return testPath, nil
+}
+
+func (b *Builder) Test(p *pkg.LocalPackage) error {
+	testPath, err := b.BuildTest(p)
+	if err != nil {
 		return err
 	}
 
 	// Run the tests.
-	if err := os.Chdir(filepath.Dir(testFilename)); err != nil {
+	if err := os.Chdir(filepath.Dir(testPath)); err != nil {
 		return err
 	}
 
 	util.StatusMessage(util.VERBOSITY_DEFAULT, "Executing test: %s\n",
-		testFilename)
-	cmd := []string{testFilename}
+		testPath)
+	cmd := []string{testPath}
 	if _, err := util.ShellCommand(cmd, nil); err != nil {
 		newtError := err.(*util.NewtError)
 		newtError.Text = fmt.Sprintf("Test failure (%s):\n%s", p.Name(),

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/builder/buildutil.go
----------------------------------------------------------------------
diff --git a/newt/builder/buildutil.go b/newt/builder/buildutil.go
index a36d3f2..c66c43a 100644
--- a/newt/builder/buildutil.go
+++ b/newt/builder/buildutil.go
@@ -33,10 +33,6 @@ func TestTargetName(testPkgName string) string {
 	return strings.Replace(testPkgName, "/", "_", -1)
 }
 
-func (b *Builder) TestExePath(bpkg *BuildPackage) string {
-	return b.PkgBinDir(bpkg) + "/" + TestTargetName(bpkg.Name())
-}
-
 func (b *Builder) FeatureString() string {
 	var buffer bytes.Buffer
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/builder/load.go
----------------------------------------------------------------------
diff --git a/newt/builder/load.go b/newt/builder/load.go
index b7ae34e..2473819 100644
--- a/newt/builder/load.go
+++ b/newt/builder/load.go
@@ -151,7 +151,6 @@ func (b *Builder) Load(imageSlot int, extraJtagCmd string) error {
 }
 
 func (t *TargetBuilder) Debug(extraJtagCmd string, reset bool, noGDB bool) error {
-	//var additional_libs []string
 	err := t.PrepBuild()
 
 	if err != nil {
@@ -164,11 +163,16 @@ func (t *TargetBuilder) Debug(extraJtagCmd string, reset bool, noGDB bool) error
 	return t.LoaderBuilder.Debug(extraJtagCmd, reset, noGDB)
 }
 
-func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool) error {
-	if b.appPkg == nil {
-		return util.NewNewtError("app package not specified")
+func (t *TargetBuilder) DebugTest() error {
+	if err := t.PrepTest(); err != nil {
+		return err
 	}
 
+	return t.AppBuilder.DebugTest(t.GetTestPkg())
+}
+
+func (b *Builder) debugBin(binPath string, extraJtagCmd string, reset bool,
+	noGDB bool) error {
 	/*
 	 * Populate the package list and feature sets.
 	 */
@@ -178,7 +182,7 @@ func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool) error {
 	}
 
 	bspPath := b.bspPkg.BasePath()
-	binBaseName := b.AppBinBasePath()
+	binBaseName := binPath
 	featureString := b.FeatureString()
 
 	coreRepo := project.GetProject().FindRepo("apache-mynewt-core")
@@ -210,3 +214,21 @@ func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool) error {
 	fmt.Printf("%s\n", cmdLine)
 	return util.ShellInteractiveCommand(cmdLine, envSettings)
 }
+
+func (b *Builder) Debug(extraJtagCmd string, reset bool, noGDB bool) error {
+	if b.appPkg == nil {
+		return util.NewNewtError("app package not specified")
+	}
+
+	return b.debugBin(b.AppBinBasePath(), extraJtagCmd, reset, noGDB)
+}
+
+func (b *Builder) DebugTest(lpkg *pkg.LocalPackage) error {
+	bpkg := b.PkgMap[lpkg]
+	if bpkg == nil {
+		panic("internal error: local package \"" + lpkg.FullName() +
+			"\" not built")
+	}
+	return b.debugBin(strings.TrimSuffix(b.TestExePath(bpkg), ".elf"),
+		"", false, false)
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/builder/paths.go
----------------------------------------------------------------------
diff --git a/newt/builder/paths.go b/newt/builder/paths.go
index fa9e940..58d1880 100644
--- a/newt/builder/paths.go
+++ b/newt/builder/paths.go
@@ -140,6 +140,10 @@ func (b *Builder) AppPath() string {
 	return b.PkgBinDir(b.appPkg) + "/"
 }
 
+func (b *Builder) TestExePath(bpkg *BuildPackage) string {
+	return b.PkgBinDir(bpkg) + "/" + TestTargetName(bpkg.Name()) + ".elf"
+}
+
 func (b *Builder) ManifestPath() string {
 	return ManifestPath(b.targetPkg.Name(), b.buildName, b.appPkg.Name())
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/builder/targetbuild.go
----------------------------------------------------------------------
diff --git a/newt/builder/targetbuild.go b/newt/builder/targetbuild.go
index 408d90d..9172800 100644
--- a/newt/builder/targetbuild.go
+++ b/newt/builder/targetbuild.go
@@ -535,7 +535,7 @@ func (t *TargetBuilder) RelinkLoader() (error, map[string]bool,
 	return err, commonPkgs, smMatch
 }
 
-func (t *TargetBuilder) Test() error {
+func (t *TargetBuilder) PrepTest() error {
 	cfgResolution, err := t.ExportCfg()
 	if err != nil {
 		return err
@@ -563,6 +563,26 @@ func (t *TargetBuilder) Test() error {
 		return err
 	}
 
+	return nil
+}
+
+func (t *TargetBuilder) BuildTest() error {
+	if err := t.PrepTest(); err != nil {
+		return err
+	}
+
+	if _, err := t.AppBuilder.BuildTest(t.testPkg); err != nil {
+		return err
+	}
+
+	return nil
+}
+
+func (t *TargetBuilder) Test() error {
+	if err := t.BuildTest(); err != nil {
+		return err
+	}
+
 	if err := t.AppBuilder.Test(t.testPkg); err != nil {
 		return err
 	}
@@ -574,6 +594,14 @@ func (t *TargetBuilder) GetTarget() *target.Target {
 	return t.target
 }
 
+func (t *TargetBuilder) GetTestPkg() *pkg.LocalPackage {
+	return t.testPkg
+}
+
+func (t *TargetBuilder) InjectSetting(key string, value string) {
+	t.injectedSettings[key] = value
+}
+
 func readManifest(path string) (*image.ImageManifest, error) {
 	content, err := ioutil.ReadFile(path)
 	if err != nil {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/cli/build_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/build_cmds.go b/newt/cli/build_cmds.go
index 0951eda..f70f4e1 100644
--- a/newt/cli/build_cmds.go
+++ b/newt/cli/build_cmds.go
@@ -417,8 +417,8 @@ func AddBuildCommands(cmd *cobra.Command) {
 		Run:   debugRunCmd,
 	}
 
-	debugCmd.PersistentFlags().StringVarP(&extraJtagCmd, "extrajtagcmd", "j", "",
-		"extra commands to send to JTAG software")
+	debugCmd.PersistentFlags().StringVarP(&extraJtagCmd, "extrajtagcmd", "j",
+		"", "extra commands to send to JTAG software")
 	debugCmd.PersistentFlags().BoolVarP(&noGDB_flag, "noGDB", "n", false,
 		"don't start GDB from command line")
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/cli/run_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/run_cmds.go b/newt/cli/run_cmds.go
index 3d94bd5..b30d5a8 100644
--- a/newt/cli/run_cmds.go
+++ b/newt/cli/run_cmds.go
@@ -23,7 +23,6 @@ import (
 	"os"
 
 	"github.com/spf13/cobra"
-	"mynewt.apache.org/newt/newt/builder"
 	"mynewt.apache.org/newt/util"
 )
 
@@ -34,44 +33,51 @@ func runRunCmd(cmd *cobra.Command, args []string) {
 
 	InitProject()
 
-	t := ResolveTarget(args[0])
-	if t == nil {
-		NewtUsage(cmd, util.NewNewtError("Invalid target name: "+args[0]))
-	}
-
-	b, err := builder.NewTargetBuilder(t)
+	b, err := TargetBuilderForTargetOrUnittest(args[0])
 	if err != nil {
-		NewtUsage(nil, err)
-	}
-
-	if err := b.Build(); err != nil {
-		NewtUsage(nil, err)
+		NewtUsage(cmd, err)
 	}
 
-	/*
-	 * Run create-image if version number is specified. If no version number,
-	 * remove .img which would'be been created. This so that download script
-	 * will barf if it needs an image for this type of target, instead of
-	 * downloading an older version.
-	 */
-	if len(args) > 1 {
-		_, _, err = b.CreateImages(args[1], "", 0)
-		if err != nil {
-			NewtUsage(cmd, err)
+	testPkg := b.GetTestPkg()
+	if testPkg != nil {
+		b.InjectSetting("TESTUTIL_SYSTEM_ASSERT", "1")
+		if err := b.BuildTest(); err != nil {
+			NewtUsage(nil, err)
+		}
+		if err := b.DebugTest(); err != nil {
+			NewtUsage(nil, err)
 		}
 	} else {
-		os.Remove(b.AppBuilder.AppImgPath())
+		if err := b.Build(); err != nil {
+			NewtUsage(nil, err)
+		}
+
+		/*
+		 * Run create-image if version number is specified. If no version
+		 * number, remove .img which would'be been created. This so that
+		 * download script will barf if it needs an image for this type of
+		 * target, instead of downloading an older version.
+		 */
+		if len(args) > 1 {
+			_, _, err = b.CreateImages(args[1], "", 0)
+			if err != nil {
+				NewtUsage(cmd, err)
+			}
+		} else {
+			os.Remove(b.AppBuilder.AppImgPath())
 
-		if b.LoaderBuilder != nil {
-			os.Remove(b.LoaderBuilder.AppImgPath())
+			if b.LoaderBuilder != nil {
+				os.Remove(b.LoaderBuilder.AppImgPath())
+			}
 		}
-	}
 
-	if err := b.Load(extraJtagCmd); err != nil {
-		NewtUsage(nil, err)
-	}
-	if err := b.Debug(extraJtagCmd, true, noGDB_flag); err != nil {
-		NewtUsage(nil, err)
+		if err := b.Load(extraJtagCmd); err != nil {
+			NewtUsage(nil, err)
+		}
+
+		if err := b.Debug(extraJtagCmd, true, noGDB_flag); err != nil {
+			NewtUsage(nil, err)
+		}
 	}
 }
 
@@ -91,12 +97,14 @@ func AddRunCommands(cmd *cobra.Command) {
 		Example: runHelpEx,
 		Run:     runRunCmd,
 	}
-	cmd.AddCommand(runCmd)
-	AddTabCompleteFn(runCmd, targetList)
 
 	runCmd.PersistentFlags().StringVarP(&extraJtagCmd, "extrajtagcmd", "j", "",
 		"extra commands to send to JTAG software")
 	runCmd.PersistentFlags().BoolVarP(&noGDB_flag, "noGDB", "n", false,
 		"don't start GDB from command line")
 
+	cmd.AddCommand(runCmd)
+	AddTabCompleteFn(runCmd, func() []string {
+		return append(targetList(), unittestList()...)
+	})
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/cli/target_cmds.go
----------------------------------------------------------------------
diff --git a/newt/cli/target_cmds.go b/newt/cli/target_cmds.go
index 4b19bbf..d2f6ebb 100644
--- a/newt/cli/target_cmds.go
+++ b/newt/cli/target_cmds.go
@@ -30,7 +30,6 @@ import (
 
 	log "github.com/Sirupsen/logrus"
 	"github.com/spf13/cobra"
-	"mynewt.apache.org/newt/newt/builder"
 	"mynewt.apache.org/newt/newt/pkg"
 	"mynewt.apache.org/newt/newt/syscfg"
 	"mynewt.apache.org/newt/newt/target"
@@ -469,41 +468,9 @@ func targetConfigCmd(cmd *cobra.Command, args []string) {
 
 	InitProject()
 
-	var b *builder.TargetBuilder
-
-	// Argument can specify either a target or a unittest package.  Determine
-	// which type the package is and construct a target builder appropriately.
-	t, err := resolveExistingTargetArg(args[0])
-	if err == nil {
-		b, err = builder.NewTargetBuilder(t)
-		if err != nil {
-			NewtUsage(nil, err)
-		}
-	} else {
-		proj := InitProject()
-
-		pack, err := proj.ResolvePackage(proj.LocalRepo(), args[0])
-		if err != nil {
-			NewtUsage(cmd, util.FmtNewtError(
-				"Could not resolve target or unittest \"%s\"", args[0]))
-		}
-
-		if pack.Type() != pkg.PACKAGE_TYPE_UNITTEST {
-			NewtUsage(cmd, util.FmtNewtError(
-				"Package \"%s\" is of type %s; "+
-					"must be target or unittest", args[0],
-				pkg.PackageTypeNames[pack.Type()]))
-		}
-
-		t, err = ResolveUnittestTarget(pack.Name())
-		if err != nil {
-			NewtUsage(nil, err)
-		}
-
-		b, err = builder.NewTargetTester(t, pack)
-		if err != nil {
-			NewtUsage(nil, err)
-		}
+	b, err := TargetBuilderForTargetOrUnittest(args[0])
+	if err != nil {
+		NewtUsage(cmd, err)
 	}
 
 	cfgResolution, err := b.ExportCfg()
@@ -518,7 +485,7 @@ func targetConfigCmd(cmd *cobra.Command, args []string) {
 		}
 	}
 
-	printCfg(t.Name(), cfgResolution.Cfg)
+	printCfg(b.GetTarget().Name(), cfgResolution.Cfg)
 }
 
 func AddTargetCommands(cmd *cobra.Command) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/cli/util.go
----------------------------------------------------------------------
diff --git a/newt/cli/util.go b/newt/cli/util.go
index afc5fc2..9b5bfe6 100644
--- a/newt/cli/util.go
+++ b/newt/cli/util.go
@@ -244,3 +244,45 @@ func ResolveUnittestTarget(pkgName string) (*target.Target, error) {
 
 	return t, nil
 }
+
+func TargetBuilderForTargetOrUnittest(pkgName string) (
+	*builder.TargetBuilder, error) {
+
+	// Argument can specify either a target or a unittest package.  Determine
+	// which type the package is and construct a target builder appropriately.
+	t, err := resolveExistingTargetArg(pkgName)
+	if err == nil {
+		b, err := builder.NewTargetBuilder(t)
+		if err != nil {
+			return nil, err
+		}
+
+		return b, nil
+	}
+
+	// Package wasn't a target.  Try for a unittest.
+	proj := InitProject()
+	pack, err := proj.ResolvePackage(proj.LocalRepo(), pkgName)
+	if err != nil {
+		return nil, util.FmtNewtError(
+			"Could not resolve target or unittest \"%s\"", pkgName)
+	}
+
+	if pack.Type() != pkg.PACKAGE_TYPE_UNITTEST {
+		return nil, util.FmtNewtError(
+			"Package \"%s\" is of type %s; "+
+				"must be target or unittest", pkgName,
+			pkg.PackageTypeNames[pack.Type()])
+	}
+
+	t, err = ResolveUnittestTarget(pack.Name())
+	if err != nil {
+		return nil, err
+	}
+
+	b, err := builder.NewTargetTester(t, pack)
+	if err != nil {
+		return nil, err
+	}
+	return b, nil
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newt/blob/199ecc0c/newt/syscfg/syscfg.go
----------------------------------------------------------------------
diff --git a/newt/syscfg/syscfg.go b/newt/syscfg/syscfg.go
index 7b4b00e..0010f56 100644
--- a/newt/syscfg/syscfg.go
+++ b/newt/syscfg/syscfg.go
@@ -182,6 +182,10 @@ func (point CfgPoint) Name() string {
 	}
 }
 
+func (point CfgPoint) IsInjected() bool {
+	return point.Source == nil
+}
+
 func (entry *CfgEntry) IsTrue() bool {
 	return ValueIsTrue(entry.Value)
 }
@@ -326,9 +330,17 @@ func (cfg *Cfg) readDefsOnce(lpkg *pkg.LocalPackage,
 					lpkg.Name(), err.Error())
 			}
 
-			if _, exists := cfg.Settings[k]; exists {
-				// XXX: Better error message.
-				return util.FmtNewtError("setting %s redefined", k)
+			if oldEntry, exists := cfg.Settings[k]; exists {
+				// Setting already defined.  Allow this only if the setting is
+				// injected, in which case the injected value takes precedence.
+				point := mostRecentPoint(oldEntry)
+				if !point.IsInjected() {
+					// XXX: Better error message.
+					return util.FmtNewtError("setting %s redefined", k)
+				}
+
+				entry.History = append(entry.History, oldEntry.History...)
+				entry.Value = oldEntry.Value
 			}
 			cfg.Settings[k] = entry
 		}