Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  microfactory_test.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2017 Google Inc. All rights reserved.
//
// 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 microfactory

import (
 "flag"
 "io/ioutil"
 "os"
 "path/filepath"
 "reflect"
 "runtime"
 "testing"
 "time"
)

func TestSimplePackagePathMap(t *testing.T) {
 t.Parallel()

 pkgMap := pkgPathMappingVar{&Config{}}
 flags := flag.NewFlagSet("", flag.ContinueOnError)
 flags.Var(&pkgMap, "m", "")
 err := flags.Parse([]string{
  "-m", "android/soong=build/soong/",
  "-m", "github.com/google/blueprint/=build/blueprint",
 })
 if err != nil {
  t.Fatal(err)
 }

 compare := func(got, want interface{}) {
  if !reflect.DeepEqual(got, want) {
   t.Errorf("Unexpected values in .pkgs:\nwant: %v\n got: %v",
    want, got)
  }
 }

 wantPkgs := []string{"android/soong", "github.com/google/blueprint"}
 compare(pkgMap.pkgs, wantPkgs)
 compare(pkgMap.paths[wantPkgs[0]], "build/soong")
 compare(pkgMap.paths[wantPkgs[1]], "build/blueprint")

 got, ok, err := pkgMap.Path("android/soong/ui/test")
 if err != nil {
  t.Error("Unexpected error in pkgMap.Path(soong):", err)
 } else if !ok {
  t.Error("Expected a result from pkgMap.Path(soong)")
 } else {
  compare(got, "build/soong/ui/test")
 }

 got, ok, err = pkgMap.Path("github.com/google/blueprint")
 if err != nil {
  t.Error("Unexpected error in pkgMap.Path(blueprint):", err)
 } else if !ok {
  t.Error("Expected a result from pkgMap.Path(blueprint)")
 } else {
  compare(got, "build/blueprint")
 }
}

func TestBadPackagePathMap(t *testing.T) {
 t.Parallel()

 pkgMap := pkgPathMappingVar{&Config{}}
 if _, _, err := pkgMap.Path("testing"); err == nil {
  t.Error("Expected error if no maps are specified")
 }
 if err := pkgMap.Set(""); err == nil {
  t.Error("Expected error with blank argument, but none returned")
 }
 if err := pkgMap.Set("a=a"); err != nil {
  t.Errorf("Unexpected error: %v", err)
 }
 if err := pkgMap.Set("a=b"); err == nil {
  t.Error("Expected error with duplicate package prefix, but none returned")
 }
 if _, ok, err := pkgMap.Path("testing"); err != nil {
  t.Errorf("Unexpected error: %v", err)
 } else if ok {
  t.Error("Expected testing to be consider in the stdlib")
 }
}

// TestSingleBuild ensures that just a basic build works.
func TestSingleBuild(t *testing.T) {
 t.Parallel()

 setupDir(t, func(config *Config, dir string, loadPkg loadPkgFunc) {
  // The output binary
  out := filepath.Join(dir, "out", "test")

  pkg := loadPkg()

  if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
   t.Fatal("Got error when compiling:", err)
  }

  if err := pkg.Link(config, out); err != nil {
   t.Fatal("Got error when linking:", err)
  }

  if _, err := os.Stat(out); err != nil {
   t.Error("Cannot stat output:", err)
  }
 })
}

// testBuildAgain triggers two builds, running the modify function in between
// each build. It verifies that the second build did or did not actually need
// to rebuild anything based on the shouldRebuild argument.
func testBuildAgain(t *testing.T,
 shouldRecompile, shouldRelink bool,
 modify func(config *Config, dir string, loadPkg loadPkgFunc),
 after func(pkg *GoPackage)) {

 t.Parallel()

 setupDir(t, func(config *Config, dir string, loadPkg loadPkgFunc) {
  // The output binary
  out := filepath.Join(dir, "out", "test")

  pkg := loadPkg()

  if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
   t.Fatal("Got error when compiling:", err)
  }

  if err := pkg.Link(config, out); err != nil {
   t.Fatal("Got error when linking:", err)
  }

  var firstTime time.Time
  if stat, err := os.Stat(out); err == nil {
   firstTime = stat.ModTime()
  } else {
   t.Fatal("Failed to stat output file:", err)
  }

  // mtime on HFS+ (the filesystem on darwin) are stored with 1
  // second granularity, so the timestamp checks will fail unless
  // we wait at least a second. Sleeping 1.1s to be safe.
  if runtime.GOOS == "darwin" {
   time.Sleep(1100 * time.Millisecond)
  }

  modify(config, dir, loadPkg)

  pkg = loadPkg()

  if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
   t.Fatal("Got error when compiling:", err)
  }
  if shouldRecompile {
   if !pkg.rebuilt {
    t.Fatal("Package should have recompiled, but was not recompiled.")
   }
  } else {
   if pkg.rebuilt {
    t.Fatal("Package should not have needed to be recompiled, but was recompiled.")
   }
  }

  if err := pkg.Link(config, out); err != nil {
   t.Fatal("Got error while linking:", err)
  }
  if shouldRelink {
   if !pkg.rebuilt {
    t.Error("Package should have relinked, but was not relinked.")
   }
  } else {
   if pkg.rebuilt {
    t.Error("Package should not have needed to be relinked, but was relinked.")
   }
  }

  if stat, err := os.Stat(out); err == nil {
   if shouldRelink {
    if stat.ModTime() == firstTime {
     t.Error("Output timestamp should be different, but both were", firstTime)
    }
   } else {
    if stat.ModTime() != firstTime {
     t.Error("Output timestamp should be the same.")
     t.Error(" first:", firstTime)
     t.Error("second:", stat.ModTime())
    }
   }
  } else {
   t.Fatal("Failed to stat output file:", err)
  }

  after(pkg)
 })
}

// TestRebuildAfterNoChanges ensures that we don't rebuild if nothing
// changes
func TestRebuildAfterNoChanges(t *testing.T) {
 testBuildAgain(t, false, false, func(config *Config, dir string, loadPkg loadPkgFunc) {}, func(pkg *GoPackage) {})
}

// TestRebuildAfterTimestamp ensures that we don't rebuild because
// timestamps of important files have changed. We should only rebuild if the
// content hashes are different.
func TestRebuildAfterTimestampChange(t *testing.T) {
 testBuildAgain(t, false, false, func(config *Config, dir string, loadPkg loadPkgFunc) {
  // Ensure that we've spent some amount of time asleep
  time.Sleep(100 * time.Millisecond)

  newTime := time.Now().Local()
  os.Chtimes(filepath.Join(dir, "test.fact"), newTime, newTime)
  os.Chtimes(filepath.Join(dir, "main/main.go"), newTime, newTime)
  os.Chtimes(filepath.Join(dir, "a/a.go"), newTime, newTime)
  os.Chtimes(filepath.Join(dir, "a/b.go"), newTime, newTime)
  os.Chtimes(filepath.Join(dir, "b/a.go"), newTime, newTime)
 }, func(pkg *GoPackage) {})
}

// TestRebuildAfterGoChange ensures that we rebuild after a content change
// to a package's go file.
func TestRebuildAfterGoChange(t *testing.T) {
 testBuildAgain(t, true, true, func(config *Config, dir string, loadPkg loadPkgFunc) {
  if err := ioutil.WriteFile(filepath.Join(dir, "a", "a.go"), []byte(go_a_a+"\n"), 0666); err != nil {
   t.Fatal("Error writing a/a.go:", err)
  }
 }, func(pkg *GoPackage) {
  if !pkg.directDeps[0].rebuilt {
   t.Fatal("android/soong/a should have rebuilt")
  }
  if !pkg.directDeps[1].rebuilt {
   t.Fatal("android/soong/b should have rebuilt")
  }
 })
}

// TestRebuildAfterMainChange ensures that we don't rebuild any dependencies
// if only the main package's go files are touched.
func TestRebuildAfterMainChange(t *testing.T) {
 testBuildAgain(t, true, true, func(config *Config, dir string, loadPkg loadPkgFunc) {
  if err := ioutil.WriteFile(filepath.Join(dir, "main", "main.go"), []byte(go_main_main+"\n"), 0666); err != nil {
   t.Fatal("Error writing main/main.go:", err)
  }
 }, func(pkg *GoPackage) {
  if pkg.directDeps[0].rebuilt {
   t.Fatal("android/soong/a should not have rebuilt")
  }
  if pkg.directDeps[1].rebuilt {
   t.Fatal("android/soong/b should not have rebuilt")
  }
 })
}

// TestRebuildAfterRemoveOut ensures that we rebuild if the output file is
// missing, even if everything else doesn't need rebuilding.
func TestRebuildAfterRemoveOut(t *testing.T) {
 testBuildAgain(t, false, true, func(config *Config, dir string, loadPkg loadPkgFunc) {
  if err := os.Remove(filepath.Join(dir, "out", "test")); err != nil {
   t.Fatal("Failed to remove output:", err)
  }
 }, func(pkg *GoPackage) {})
}

// TestRebuildAfterPartialBuild ensures that even if the build was interrupted
// between the recompile and relink stages, we'll still relink when we run again.
func TestRebuildAfterPartialBuild(t *testing.T) {
 testBuildAgain(t, false, true, func(config *Config, dir string, loadPkg loadPkgFunc) {
  if err := ioutil.WriteFile(filepath.Join(dir, "main", "main.go"), []byte(go_main_main+"\n"), 0666); err != nil {
   t.Fatal("Error writing main/main.go:", err)
  }

  pkg := loadPkg()

  if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
   t.Fatal("Got error when compiling:", err)
  }
  if !pkg.rebuilt {
   t.Fatal("Package should have recompiled, but was not recompiled.")
  }
 }, func(pkg *GoPackage) {})
}

// BenchmarkInitialBuild computes how long a clean build takes (for tiny test
// inputs).
func BenchmarkInitialBuild(b *testing.B) {
 for i := 0; i < b.N; i++ {
  setupDir(b, func(config *Config, dir string, loadPkg loadPkgFunc) {
   pkg := loadPkg()
   if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
    b.Fatal("Got error when compiling:", err)
   }

   if err := pkg.Link(config, filepath.Join(dir, "out", "test")); err != nil {
    b.Fatal("Got error when linking:", err)
   }
  })
 }
}

// BenchmarkMinIncrementalBuild computes how long an incremental build that
// doesn't actually need to build anything takes.
func BenchmarkMinIncrementalBuild(b *testing.B) {
 setupDir(b, func(config *Config, dir string, loadPkg loadPkgFunc) {
  pkg := loadPkg()

  if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
   b.Fatal("Got error when compiling:", err)
  }

  if err := pkg.Link(config, filepath.Join(dir, "out", "test")); err != nil {
   b.Fatal("Got error when linking:", err)
  }

  b.ResetTimer()

  for i := 0; i < b.N; i++ {
   pkg := loadPkg()

   if err := pkg.Compile(config, filepath.Join(dir, "out")); err != nil {
    b.Fatal("Got error when compiling:", err)
   }

   if err := pkg.Link(config, filepath.Join(dir, "out", "test")); err != nil {
    b.Fatal("Got error when linking:", err)
   }

   if pkg.rebuilt {
    b.Fatal("Should not have rebuilt anything")
   }
  }
 })
}

///////////////////////////////////////////////////////
// Templates used to create fake compilable packages //
///////////////////////////////////////////////////////

const go_main_main = `
package main
import (
 "fmt"
 "android/soong/a"
 "android/soong/b"
)
func main() {
 fmt.Println(a.Stdout, b.Stdout)
}
`

const go_a_a = `
package a
import "os"
var Stdout = os.Stdout
`

const go_a_b = `
package a
`

const go_b_a = `
package b
import "android/soong/a"
var Stdout = a.Stdout
`

type T interface {
 Fatal(args ...interface{})
 Fatalf(format string, args ...interface{})
}

type loadPkgFunc func() *GoPackage

func setupDir(t T, test func(config *Config, dir string, loadPkg loadPkgFunc)) {
 dir, err := ioutil.TempDir("", "test")
 if err != nil {
  t.Fatalf("Error creating temporary directory: %#v", err)
 }
 defer os.RemoveAll(dir)

 writeFile := func(name, contents string) {
  if err := ioutil.WriteFile(filepath.Join(dir, name), []byte(contents), 0666); err != nil {
   t.Fatalf("Error writing %q: %#v", name, err)
  }
 }
 mkdir := func(name string) {
  if err := os.Mkdir(filepath.Join(dir, name), 0777); err != nil {
   t.Fatalf("Error creating %q directory: %#v", name, err)
  }
 }
 mkdir("main")
 mkdir("a")
 mkdir("b")
 writeFile("main/main.go", go_main_main)
 writeFile("a/a.go", go_a_a)
 writeFile("a/b.go", go_a_b)
 writeFile("b/a.go", go_b_a)

 config := &Config{}
 config.Map("android/soong", dir)

 loadPkg := func() *GoPackage {
  pkg := &GoPackage{
   Name: "main",
  }
  if err := pkg.FindDeps(config, filepath.Join(dir, "main")); err != nil {
   t.Fatalf("Error finding deps: %v", err)
  }
  return pkg
 }

 test(config, dir, loadPkg)
}

[Dauer der Verarbeitung: 0.25 Sekunden, vorverarbeitet 2026-06-28]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik