Eine aufbereitete Darstellung der Quelle

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

Benutzer

Quelle  test_util.go   Sprache: unbekannt

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

// Copyright 2021 Google LLC
//
// 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 compliance

import (
 "fmt"
 "io"
 "sort"
 "strings"
 "testing"

 "android/soong/tools/compliance/testfs"
)

const (
 // AOSP starts a test metadata file for Android Apache-2.0 licensing.
 AOSP = `` +
  `package_name: "Android"
license_kinds: "SPDX-license-identifier-Apache-2.0"
license_conditions: "notice"
`

 // GPL starts a test metadata file for GPL 2.0 licensing.
 GPL = `` +
  `package_name: "Free Software"
license_kinds: "SPDX-license-identifier-GPL-2.0"
license_conditions: "restricted"
`

 // Classpath starts a test metadata file for GPL 2.0 with classpath exception licensing.
 Classpath = `` +
  `package_name: "Free Software"
license_kinds: "SPDX-license-identifier-GPL-2.0-with-classpath-exception"
license_conditions: "permissive"
`

 // DependentModule starts a test metadata file for a module in the same package as `Classpath`.
 DependentModule = `` +
  `package_name: "Free Software"
license_kinds: "SPDX-license-identifier-MIT"
license_conditions: "notice"
`

 // LGPL starts a test metadata file for a module with LGPL 2.0 licensing.
 LGPL = `` +
  `package_name: "Free Library"
license_kinds: "SPDX-license-identifier-LGPL-2.0"
license_conditions: "restricted_if_statically_linked"
`

 // MPL starts a test metadata file for a module with MPL 2.0 reciprical licensing.
 MPL = `` +
  `package_name: "Reciprocal"
license_kinds: "SPDX-license-identifier-MPL-2.0"
license_conditions: "reciprocal"
`

 // MIT starts a test metadata file for a module with generic notice (MIT) licensing.
 MIT = `` +
  `package_name: "Android"
license_kinds: "SPDX-license-identifier-MIT"
license_conditions: "notice"
`

 // Proprietary starts a test metadata file for a module with proprietary licensing.
 Proprietary = `` +
  `package_name: "Android"
license_kinds: "legacy_proprietary"
license_conditions: "proprietary"
`

 // ByException starts a test metadata file for a module with by_exception_only licensing.
 ByException = `` +
  `package_name: "Special"
license_kinds: "legacy_by_exception_only"
license_conditions: "by_exception_only"
`
)

var (
 // meta maps test file names to metadata file content without dependencies.
 meta = map[string]string{
  "apacheBin.meta_lic":                 AOSP,
  "apacheLib.meta_lic":                 AOSP,
  "apacheContainer.meta_lic":           AOSP + "is_container: true\n",
  "dependentModule.meta_lic":           DependentModule,
  "gplWithClasspathException.meta_lic": Classpath,
  "gplBin.meta_lic":                    GPL,
  "gplLib.meta_lic":                    GPL,
  "gplContainer.meta_lic":              GPL + "is_container: true\n",
  "lgplBin.meta_lic":                   LGPL,
  "lgplLib.meta_lic":                   LGPL,
  "mitBin.meta_lic":                    MIT,
  "mitLib.meta_lic":                    MIT,
  "mplBin.meta_lic":                    MPL,
  "mplLib.meta_lic":                    MPL,
  "proprietary.meta_lic":               Proprietary,
  "by_exception.meta_lic":              ByException,
 }
)

// newTestNode constructs a test node in the license graph.
func newTestNode(lg *LicenseGraph, targetName string) *TargetNode {
 if tn, alreadyExists := lg.targets[targetName]; alreadyExists {
  return tn
 }
 tn := &TargetNode{name: targetName}
 lg.targets[targetName] = tn
 return tn
}

// newTestCondition constructs a test license condition.
func newTestCondition(conditionName string) LicenseCondition {
 cl := LicenseConditionSetFromNames(conditionName).AsList()
 if len(cl) == 0 {
  panic(fmt.Errorf("attempt to create unrecognized condition: %q", conditionName))
 } else if len(cl) != 1 {
  panic(fmt.Errorf("unexpected multiple conditions from condition name: %q: got %d, want 1", conditionName, len(cl)))
 }
 lc := cl[0]
 return lc
}

// newTestConditionSet constructs a test license condition set.
func newTestConditionSet(conditionName []string) LicenseConditionSet {
 cs := LicenseConditionSetFromNames(conditionName...)
 if cs.IsEmpty() {
  panic(fmt.Errorf("attempt to create unrecognized condition: %q", conditionName))
 }
 return cs
}

// edge describes test data edges to define test graphs.
type edge struct {
 target, dep string
}

// String returns a string representation of the edge.
func (e edge) String() string {
 return e.target + " -> " + e.dep
}

// byEdge orders edges by target then dep name then annotations.
type byEdge []edge

// Len returns the count of elements in the slice.
func (l byEdge) Len() int { return len(l) }

// Swap rearranges 2 elements of the slice so that each occupies the other's
// former position.
func (l byEdge) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

// Less returns true when the `i`th element is lexicographically less than
// the `j`th element.
func (l byEdge) Less(i, j int) bool {
 if l[i].target == l[j].target {
  return l[i].dep < l[j].dep
 }
 return l[i].target < l[j].target
}

// annotated describes annotated test data edges to define test graphs.
type annotated struct {
 target, dep string
 annotations []string
}

func (e annotated) String() string {
 if e.annotations != nil {
  return e.target + " -> " + e.dep + " [" + strings.Join(e.annotations, ", ") + "]"
 }
 return e.target + " -> " + e.dep
}

func (e annotated) IsEqualTo(other annotated) bool {
 if e.target != other.target {
  return false
 }
 if e.dep != other.dep {
  return false
 }
 if len(e.annotations) != len(other.annotations) {
  return false
 }
 a1 := append([]string{}, e.annotations...)
 a2 := append([]string{}, other.annotations...)
 for i := 0; i < len(a1); i++ {
  if a1[i] != a2[i] {
   return false
  }
 }
 return true
}

// toGraph converts a list of roots and a list of annotated edges into a test license graph.
func toGraph(stderr io.Writer, roots []string, edges []annotated) (*LicenseGraph, error) {
 deps := make(map[string][]annotated)
 for _, root := range roots {
  deps[root] = []annotated{}
 }
 for _, edge := range edges {
  if prev, ok := deps[edge.target]; ok {
   deps[edge.target] = append(prev, edge)
  } else {
   deps[edge.target] = []annotated{edge}
  }
  if _, ok := deps[edge.dep]; !ok {
   deps[edge.dep] = []annotated{}
  }
 }
 fs := make(testfs.TestFS)
 for file, edges := range deps {
  body := meta[file]
  for _, edge := range edges {
   body += fmt.Sprintf("deps: {\n  file: %q\n", edge.dep)
   for _, ann := range edge.annotations {
    body += fmt.Sprintf("  annotations: %q\n", ann)
   }
   body += "}\n"
  }
  fs[file] = []byte(body)
 }

 return ReadLicenseGraph(&fs, stderr, roots)
}

// logGraph outputs a representation of the graph to a test log.
func logGraph(lg *LicenseGraph, t *testing.T) {
 t.Logf("license graph:")
 t.Logf("  targets:")
 for _, target := range lg.Targets() {
  t.Logf("    %s%s in package %q", target.Name(), target.LicenseConditions().String(), target.PackageName())
 }
 t.Logf("  /targets")
 t.Logf("  edges:")
 for _, edge := range lg.Edges() {
  t.Logf("    %s", edge.String())
 }
 t.Logf("  /edges")
 t.Logf("/license graph")
}

// byAnnotatedEdge orders edges by target then dep name then annotations.
type byAnnotatedEdge []annotated

func (l byAnnotatedEdge) Len() int      { return len(l) }
func (l byAnnotatedEdge) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l byAnnotatedEdge) Less(i, j int) bool {
 if l[i].target == l[j].target {
  if l[i].dep == l[j].dep {
   ai := append([]string{}, l[i].annotations...)
   aj := append([]string{}, l[j].annotations...)
   sort.Strings(ai)
   sort.Strings(aj)
   for k := 0; k < len(ai) && k < len(aj); k++ {
    if ai[k] == aj[k] {
     continue
    }
    return ai[k] < aj[k]
   }
   return len(ai) < len(aj)
  }
  return l[i].dep < l[j].dep
 }
 return l[i].target < l[j].target
}

// act describes test data resolution actions to define test action sets.
type act struct {
 actsOn, condition string
}

// String returns a human-readable string representing the test action.
func (a act) String() string {
 return fmt.Sprintf("%s{%s}", a.actsOn, a.condition)
}

// toActionSet converts a list of act test data into a test action set.
func toActionSet(lg *LicenseGraph, data []act) ActionSet {
 as := make(ActionSet)
 for _, a := range data {
  actsOn := newTestNode(lg, a.actsOn)
  cs := newTestConditionSet(strings.Split(a.condition, "|"))
  as[actsOn] = cs
 }
 return as
}

// res describes test data resolutions to define test resolution sets.
type res struct {
 attachesTo, actsOn, condition string
}

// toResolutionSet converts a list of res test data into a test resolution set.
func toResolutionSet(lg *LicenseGraph, data []res) ResolutionSet {
 rmap := make(ResolutionSet)
 for _, r := range data {
  attachesTo := newTestNode(lg, r.attachesTo)
  actsOn := newTestNode(lg, r.actsOn)
  if _, ok := rmap[attachesTo]; !ok {
   rmap[attachesTo] = make(ActionSet)
  }
  cs := newTestConditionSet(strings.Split(r.condition, "|"))
  rmap[attachesTo][actsOn] |= cs
 }
 return rmap
}

// tcond associates a target name with '|' separated string conditions.
type tcond struct {
 target, conditions string
}

// action represents a single element of an ActionSet for testing.
type action struct {
 target *TargetNode
 cs     LicenseConditionSet
}

// String returns a human-readable string representation of the action.
func (a action) String() string {
 return fmt.Sprintf("%s%s", a.target.Name(), a.cs.String())
}

// actionList represents an array of actions and a total order defined by
// target name followed by license condition set.
type actionList []action

// String returns a human-readable string representation of the list.
func (l actionList) String() string {
 var sb strings.Builder
 fmt.Fprintf(&sb, "[")
 sep := ""
 for _, a := range l {
  fmt.Fprintf(&sb, "%s%s", sep, a.String())
  sep = ", "
 }
 fmt.Fprintf(&sb, "]")
 return sb.String()
}

// Len returns the count of elements in the slice.
func (l actionList) Len() int { return len(l) }

// Swap rearranges 2 elements of the slice so that each occupies the other's
// former position.
func (l actionList) Swap(i, j int) { l[i], l[j] = l[j], l[i] }

// Less returns true when the `i`th element is lexicographically less than
// the `j`th element.
func (l actionList) Less(i, j int) bool {
 if l[i].target == l[j].target {
  return l[i].cs < l[j].cs
 }
 return l[i].target.Name() < l[j].target.Name()
}

// asActionList represents the resolved license conditions in a license graph
// as an actionList for comparison in a test.
func asActionList(lg *LicenseGraph) actionList {
 result := make(actionList, 0, len(lg.targets))
 for _, target := range lg.targets {
  cs := target.resolution
  if cs.IsEmpty() {
   continue
  }
  result = append(result, action{target, cs})
 }
 return result
}

// toActionList converts an array of tcond into an actionList for comparison
// in a test.
func toActionList(lg *LicenseGraph, actions []tcond) actionList {
 result := make(actionList, 0, len(actions))
 for _, actn := range actions {
  target := newTestNode(lg, actn.target)
  cs := NewLicenseConditionSet()
  for _, name := range strings.Split(actn.conditions, "|") {
   lc, ok := RecognizedConditionNames[name]
   if !ok {
    panic(fmt.Errorf("Unrecognized test condition name: %q", name))
   }
   cs = cs.Plus(lc)
  }
  result = append(result, action{target, cs})
 }
 return result
}

// confl defines test data for a SourceSharePrivacyConflict as a target name,
// source condition name, privacy condition name triple.
type confl struct {
 sourceNode, share, privacy string
}

// toConflictList converts confl test data into an array of
// SourceSharePrivacyConflict for comparison in a test.
func toConflictList(lg *LicenseGraph, data []confl) []SourceSharePrivacyConflict {
 result := make([]SourceSharePrivacyConflict, 0, len(data))
 for _, c := range data {
  fields := strings.Split(c.share, ":")
  cshare := fields[1]
  fields = strings.Split(c.privacy, ":")
  cprivacy := fields[1]
  result = append(result, SourceSharePrivacyConflict{
   newTestNode(lg, c.sourceNode),
   newTestCondition(cshare),
   newTestCondition(cprivacy),
  })
 }
 return result
}

// checkSameActions compares an actual action set to an expected action set for a test.
func checkSameActions(lg *LicenseGraph, asActual, asExpected ActionSet, t *testing.T) {
 rsActual := make(ResolutionSet)
 rsExpected := make(ResolutionSet)
 testNode := newTestNode(lg, "test")
 rsActual[testNode] = asActual
 rsExpected[testNode] = asExpected
 checkSame(rsActual, rsExpected, t)
}

// checkSame compares an actual resolution set to an expected resolution set for a test.
func checkSame(rsActual, rsExpected ResolutionSet, t *testing.T) {
 t.Logf("actual resolution set: %s", rsActual.String())
 t.Logf("expected resolution set: %s", rsExpected.String())

 actualTargets := rsActual.AttachesTo()
 sort.Sort(actualTargets)

 expectedTargets := rsExpected.AttachesTo()
 sort.Sort(expectedTargets)

 t.Logf("actual targets: %s", actualTargets.String())
 t.Logf("expected targets: %s", expectedTargets.String())

 for _, target := range expectedTargets {
  if !rsActual.AttachesToTarget(target) {
   t.Errorf("unexpected missing target: got AttachesToTarget(%q) is false, want true", target.name)
   continue
  }
  expectedRl := rsExpected.Resolutions(target)
  sort.Sort(expectedRl)
  actualRl := rsActual.Resolutions(target)
  sort.Sort(actualRl)
  if len(expectedRl) != len(actualRl) {
   t.Errorf("unexpected number of resolutions attach to %q: %d elements, %d elements",
    target.name, len(actualRl), len(expectedRl))
   continue
  }
  for i := 0; i < len(expectedRl); i++ {
   if expectedRl[i].attachesTo.name != actualRl[i].attachesTo.name || expectedRl[i].actsOn.name != actualRl[i].actsOn.name {
    t.Errorf("unexpected resolution attaches to %q at index %d: got %s, want %s",
     target.name, i, actualRl[i].asString(), expectedRl[i].asString())
    continue
   }
   expectedConditions := expectedRl[i].Resolves()
   actualConditions := actualRl[i].Resolves()
   if expectedConditions != actualConditions {
    t.Errorf("unexpected conditions apply to %q acting on %q: got %#v with names %s, want %#v with names %s",
     target.name, expectedRl[i].actsOn.name,
     actualConditions, actualConditions.Names(),
     expectedConditions, expectedConditions.Names())
    continue
   }
  }

 }
 for _, target := range actualTargets {
  if !rsExpected.AttachesToTarget(target) {
   t.Errorf("unexpected extra target: got expected.AttachesTo(%q) is false, want true", target.name)
  }
 }
}

// checkResolvesActions compares an actual action set to an expected action set for a test verifying the actual set
// resolves all of the expected conditions.
func checkResolvesActions(lg *LicenseGraph, asActual, asExpected ActionSet, t *testing.T) {
 rsActual := make(ResolutionSet)
 rsExpected := make(ResolutionSet)
 testNode := newTestNode(lg, "test")
 rsActual[testNode] = asActual
 rsExpected[testNode] = asExpected
 checkResolves(rsActual, rsExpected, t)
}

// checkResolves compares an actual resolution set to an expected resolution set for a test verifying the actual set
// resolves all of the expected conditions.
func checkResolves(rsActual, rsExpected ResolutionSet, t *testing.T) {
 t.Logf("actual resolution set: %s", rsActual.String())
 t.Logf("expected resolution set: %s", rsExpected.String())

 actualTargets := rsActual.AttachesTo()
 sort.Sort(actualTargets)

 expectedTargets := rsExpected.AttachesTo()
 sort.Sort(expectedTargets)

 t.Logf("actual targets: %s", actualTargets.String())
 t.Logf("expected targets: %s", expectedTargets.String())

 for _, target := range expectedTargets {
  if !rsActual.AttachesToTarget(target) {
   t.Errorf("unexpected missing target: got AttachesToTarget(%q) is false, want true", target.name)
   continue
  }
  expectedRl := rsExpected.Resolutions(target)
  sort.Sort(expectedRl)
  actualRl := rsActual.Resolutions(target)
  sort.Sort(actualRl)
  if len(expectedRl) != len(actualRl) {
   t.Errorf("unexpected number of resolutions attach to %q: %d elements, %d elements",
    target.name, len(actualRl), len(expectedRl))
   continue
  }
  for i := 0; i < len(expectedRl); i++ {
   if expectedRl[i].attachesTo.name != actualRl[i].attachesTo.name || expectedRl[i].actsOn.name != actualRl[i].actsOn.name {
    t.Errorf("unexpected resolution attaches to %q at index %d: got %s, want %s",
     target.name, i, actualRl[i].asString(), expectedRl[i].asString())
    continue
   }
   expectedConditions := expectedRl[i].Resolves()
   actualConditions := actualRl[i].Resolves()
   if expectedConditions != (expectedConditions & actualConditions) {
    t.Errorf("expected conditions missing from %q acting on %q: got %#v with names %s, want %#v with names %s",
     target.name, expectedRl[i].actsOn.name,
     actualConditions, actualConditions.Names(),
     expectedConditions, expectedConditions.Names())
    continue
   }
  }

 }
 for _, target := range actualTargets {
  if !rsExpected.AttachesToTarget(target) {
   t.Errorf("unexpected extra target: got expected.AttachesTo(%q) is false, want true", target.name)
  }
 }
}

[Dauer der Verarbeitung: 0.24 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