Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/blueprint/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 17 kB image not shown  

Quelle  provider_test.go   Sprache: unbekannt

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

// Copyright 2020 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 blueprint

import (
 "bytes"
 "fmt"
 "reflect"
 "strings"
 "testing"

 "github.com/google/blueprint/gobtools"
)

type providerTestModule struct {
 ModuleBase
 SimpleName
 properties struct {
  Deps []string
 }

 mutatorProviderValues              []string
 generateBuildActionsProviderValues []string
}

func newProviderTestModule() (Module, []interface{}) {
 m := &providerTestModule{}
 return m, []interface{}{&m.properties, &m.SimpleName.Properties}
}

var providerTestSingletonProvider = NewSingletonProvider[bool]()

type providerTestParallelSingleton struct {
 visitAllSingletons bool
}

func (s *providerTestParallelSingleton) GenerateBuildActions(ctx SingletonContext) {
 if s.visitAllSingletons {
  ctx.VisitAllSingletons(func(s SingletonProxy) {})
 }
 ctx.SetSingletonProvider(providerTestSingletonProvider, true)
}

func (s *providerTestParallelSingleton) IncrementalSupported() bool {
 return true
}

type providerTestSequentialSingleton struct {
 getModuleProvider bool
 setModuleProvider bool
}

func (s *providerTestSequentialSingleton) GenerateBuildActions(ctx SingletonContext) {
 if s.getModuleProvider {
  ctx.VisitAllSingletons(func(s SingletonProxy) {
   ctx.OtherSingletonProvider(s, providerTestMutatorInfoProvider)
  })
 }
 if s.setModuleProvider {
  ctx.SetSingletonProvider(providerTestMutatorInfoProvider, nil)
 }
 ctx.VisitAllSingletons(func(s SingletonProxy) {
  ctx.OtherSingletonProvider(s, providerTestSingletonProvider)
 })
}

func (s *providerTestSequentialSingleton) IncrementalSupported() bool {
 return true
}

type providerTestMutatorInfo struct {
 Values []string
}

type providerTestGenerateBuildActionsInfo struct {
 Value string
}

func (providerTestGenerateBuildActionsInfo) Encode(ctx gobtools.EncContext, buf *bytes.Buffer) error {
 return nil
}

func (providerTestGenerateBuildActionsInfo) GetTypeId() int16 {
 return -1
}

type providerTestUnsetInfo string

var providerTestMutatorInfoProvider = NewMutatorProvider[*providerTestMutatorInfo]("provider_mutator")
var providerTestGenerateBuildActionsInfoProvider = NewProvider[*providerTestGenerateBuildActionsInfo]()
var providerTestUnsetInfoProvider = NewMutatorProvider[providerTestUnsetInfo]("provider_mutator")
var providerTestUnusedMutatorProvider = NewMutatorProvider[*struct{ unused string }]("nonexistent_mutator")

func (p *providerTestModule) GenerateBuildActions(ctx ModuleContext) {
 unset, ok := ModuleProvider(ctx, providerTestUnsetInfoProvider)
 if ok {
  panic(fmt.Errorf("expected false return value for providerTestGenerateBuildActionsInfoProvider before it was set"))
 }
 if unset != "" {
  panic(fmt.Errorf("expected zero value for providerTestGenerateBuildActionsInfoProvider before it was set, got %q",
   unset))
 }

 // Verify reading providerTestUnusedMutatorProvider doesn't panic
 _, _ = ModuleProvider(ctx, providerTestUnusedMutatorProvider)

 SetProvider(ctx, providerTestGenerateBuildActionsInfoProvider, &providerTestGenerateBuildActionsInfo{
  Value: ctx.ModuleName(),
 })

 mp, ok := ModuleProvider(ctx, providerTestMutatorInfoProvider)
 if ok {
  p.mutatorProviderValues = mp.Values
 }

 ctx.VisitDirectDeps(func(module Module) {
  gbap, _ := OtherModuleProvider(ctx, module, providerTestGenerateBuildActionsInfoProvider)
  if gbap != nil {
   p.generateBuildActionsProviderValues = append(p.generateBuildActionsProviderValues, gbap.Value)
  }
 })
}

func providerTestDepsMutator(ctx BottomUpMutatorContext) {
 if p, ok := ctx.Module().(*providerTestModule); ok {
  ctx.AddDependency(ctx.Module(), nil, p.properties.Deps...)
 }
}

func providerTestMutator(ctx BottomUpMutatorContext) {
 values := []string{strings.ToLower(ctx.ModuleName())}

 ctx.VisitDirectDeps(func(module Module) {
  mp, _ := OtherModuleProvider(ctx, module, providerTestMutatorInfoProvider)
  if mp != nil {
   values = append(values, mp.Values...)
  }
 })

 SetProvider(ctx, providerTestMutatorInfoProvider, &providerTestMutatorInfo{
  Values: values,
 })
}

func providerTestAfterMutator(ctx BottomUpMutatorContext) {
 // Verify reading providerTestUnusedMutatorProvider doesn't panic
 _, _ = ModuleProvider(ctx, providerTestMutatorInfoProvider)
}

func TestProviders(t *testing.T) {
 ctx := NewContext()
 ctx.RegisterModuleType("provider_module", newProviderTestModule)
 ctx.RegisterBottomUpMutator("provider_deps_mutator", providerTestDepsMutator)
 ctx.RegisterBottomUpMutator("provider_mutator", providerTestMutator)
 ctx.RegisterBottomUpMutator("provider_after_mutator", providerTestAfterMutator)

 ctx.MockFileSystem(map[string][]byte{
  "Android.bp": []byte(`
   provider_module {
    name: "A",
    deps: ["B"],
   }
 
   provider_module {
    name: "B",
    deps: ["C", "D"],
   }
 
   provider_module {
    name: "C",
    deps: ["D"],
   }
 
   provider_module {
    name: "D",
   }
  `),
 })

 _, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)
 if len(errs) == 0 {
  _, errs = ctx.ResolveDependencies(nil)
 }
 if len(errs) == 0 {
  _, errs = ctx.PrepareBuildActions(nil)
 }
 if len(errs) > 0 {
  t.Errorf("unexpected errors:")
  for _, err := range errs {
   t.Errorf("  %s", err)
  }
  t.FailNow()
 }

 aModule := ctx.moduleGroupFromName("A", nil).moduleByVariantName("").logicModule.(*providerTestModule)
 if g, w := aModule.generateBuildActionsProviderValues, []string{"B"}; !reflect.DeepEqual(g, w) {
  t.Errorf("expected A.generateBuildActionsProviderValues %q, got %q", w, g)
 }
 if g, w := aModule.mutatorProviderValues, []string{"a", "b", "c", "d", "d"}; !reflect.DeepEqual(g, w) {
  t.Errorf("expected A.mutatorProviderValues %q, got %q", w, g)
 }

 bModule := ctx.moduleGroupFromName("B", nil).moduleByVariantName("").logicModule.(*providerTestModule)
 if g, w := bModule.generateBuildActionsProviderValues, []string{"C", "D"}; !reflect.DeepEqual(g, w) {
  t.Errorf("expected B.generateBuildActionsProviderValues %q, got %q", w, g)
 }
 if g, w := bModule.mutatorProviderValues, []string{"b", "c", "d", "d"}; !reflect.DeepEqual(g, w) {
  t.Errorf("expected B.mutatorProviderValues %q, got %q", w, g)
 }
}

type invalidProviderUsageMutatorInfo string
type invalidProviderUsageGenerateBuildActionsInfo string

func (invalidProviderUsageGenerateBuildActionsInfo) Encode(ctx gobtools.EncContext, buf *bytes.Buffer) error {
 return nil
}

func (invalidProviderUsageGenerateBuildActionsInfo) GetTypeId() int16 {
 return -1
}

var invalidProviderUsageMutatorInfoProvider = NewMutatorProvider[invalidProviderUsageMutatorInfo]("mutator_under_test")
var invalidProviderUsageGenerateBuildActionsInfoProvider = NewProvider[invalidProviderUsageGenerateBuildActionsInfo]()

type invalidProviderUsageTestModule struct {
 ModuleBase
 SimpleName
 properties struct {
  Deps []string

  Early_mutator_set_of_mutator_provider       bool
  Late_mutator_set_of_mutator_provider        bool
  Late_build_actions_set_of_mutator_provider  bool
  Early_mutator_set_of_build_actions_provider bool

  Early_mutator_get_of_mutator_provider       bool
  Early_mutator_get_of_build_actions_provider bool

  Duplicate_set bool
 }
}

func invalidProviderUsageDepsMutator(ctx BottomUpMutatorContext) {
 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
  ctx.AddDependency(ctx.Module(), nil, i.properties.Deps...)
 }
}

func invalidProviderUsageBeforeMutator(ctx BottomUpMutatorContext) {
 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
  if i.properties.Early_mutator_set_of_mutator_provider {
   // A mutator attempting to set the value of a provider associated with a later mutator.
   SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
  }
  if i.properties.Early_mutator_get_of_mutator_provider {
   // A mutator attempting to get the value of a provider associated with a later mutator.
   _, _ = ModuleProvider(ctx, invalidProviderUsageMutatorInfoProvider)
  }
 }
}

func invalidProviderUsageMutatorUnderTest(ctx BottomUpMutatorContext) {
 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
  if i.properties.Early_mutator_set_of_build_actions_provider {
   // A mutator attempting to set the value of a non-mutator provider.
   SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
  }
  if i.properties.Early_mutator_get_of_build_actions_provider {
   // A mutator attempting to get the value of a non-mutator provider.
   _, _ = ModuleProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider)
  }
 }
}

func invalidProviderUsageAfterMutator(ctx BottomUpMutatorContext) {
 if i, ok := ctx.Module().(*invalidProviderUsageTestModule); ok {
  if i.properties.Late_mutator_set_of_mutator_provider {
   // A mutator trying to set the value of a provider associated with an earlier mutator.
   SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
  }
  if i.properties.Late_mutator_set_of_mutator_provider {
   // A mutator trying to set the value of a provider associated with an earlier mutator.
   SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
  }
 }
}

func (i *invalidProviderUsageTestModule) GenerateBuildActions(ctx ModuleContext) {
 if i.properties.Late_build_actions_set_of_mutator_provider {
  // A GenerateBuildActions trying to set the value of a provider associated with a mutator.
  SetProvider(ctx, invalidProviderUsageMutatorInfoProvider, invalidProviderUsageMutatorInfo(""))
 }
 if i.properties.Duplicate_set {
  SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
  SetProvider(ctx, invalidProviderUsageGenerateBuildActionsInfoProvider, invalidProviderUsageGenerateBuildActionsInfo(""))
 }
}

func TestInvalidProvidersUsage(t *testing.T) {
 run := func(t *testing.T, module string, prop string, panicMsg string) {
  t.Helper()
  ctx := NewContext()
  ctx.RegisterModuleType("invalid_provider_usage_test_module", func() (Module, []interface{}) {
   m := &invalidProviderUsageTestModule{}
   return m, []interface{}{&m.properties, &m.SimpleName.Properties}
  })
  ctx.RegisterBottomUpMutator("deps", invalidProviderUsageDepsMutator)
  ctx.RegisterBottomUpMutator("before", invalidProviderUsageBeforeMutator)
  ctx.RegisterBottomUpMutator("mutator_under_test", invalidProviderUsageMutatorUnderTest)
  ctx.RegisterBottomUpMutator("after", invalidProviderUsageAfterMutator)

  // Don't invalidate the parent pointer and before GenerateBuildActions.
  ctx.SkipCloneModulesAfterMutators = true

  var parentBP, moduleUnderTestBP, childBP string

  prop += ": true,"

  switch module {
  case "parent":
   parentBP = prop
  case "module_under_test":
   moduleUnderTestBP = prop
  case "child":
   childBP = prop
  }

  bp := fmt.Sprintf(`
   invalid_provider_usage_test_module {
    name: "parent",
    deps: ["module_under_test"],
    %s
   }
 
   invalid_provider_usage_test_module {
    name: "module_under_test",
    deps: ["child"],
    %s
   }
 
   invalid_provider_usage_test_module {
    name: "child",
    %s
   }

  `,
   parentBP,
   moduleUnderTestBP,
   childBP)

  ctx.MockFileSystem(map[string][]byte{
   "Android.bp": []byte(bp),
  })

  _, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)

  if len(errs) == 0 {
   _, errs = ctx.ResolveDependencies(nil)
  }

  if len(errs) == 0 {
   _, errs = ctx.PrepareBuildActions(nil)
  }

  if len(errs) == 0 {
   t.Fatal("expected an error")
  }

  if len(errs) > 1 {
   t.Errorf("expected a single error, got %d:", len(errs))
   for i, err := range errs {
    t.Errorf("%d:  %s", i, err)
   }
   t.FailNow()
  }

  if panicErr, ok := errs[0].(panicError); ok {
   if panicErr.panic != panicMsg {
    t.Fatalf("expected panic %q, got %q", panicMsg, panicErr.panic)
   }
  } else {
   t.Fatalf("expected a panicError, got %T: %s", errs[0], errs[0].Error())
  }

 }

 tests := []struct {
  prop   string
  module string

  panicMsg string
  skip     string
 }{
  {
   prop:     "early_mutator_set_of_mutator_provider",
   module:   "module_under_test",
   panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test started",
  },
  {
   prop:     "late_mutator_set_of_mutator_provider",
   module:   "module_under_test",
   panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished",
  },
  {
   prop:     "late_build_actions_set_of_mutator_provider",
   module:   "module_under_test",
   panicMsg: "Can't set value of provider blueprint.invalidProviderUsageMutatorInfo after mutator mutator_under_test finished",
  },
  {
   prop:     "early_mutator_set_of_build_actions_provider",
   module:   "module_under_test",
   panicMsg: "Can't set value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions started",
  },

  {
   prop:     "early_mutator_get_of_mutator_provider",
   module:   "module_under_test",
   panicMsg: "Can't get value of provider blueprint.invalidProviderUsageMutatorInfo before mutator mutator_under_test finished",
  },
  {
   prop:     "early_mutator_get_of_build_actions_provider",
   module:   "module_under_test",
   panicMsg: "Can't get value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo before GenerateBuildActions finished",
  },
  {
   prop:     "duplicate_set",
   module:   "module_under_test",
   panicMsg: "Value of provider blueprint.invalidProviderUsageGenerateBuildActionsInfo is already set",
  },
 }

 for _, tt := range tests {
  t.Run(tt.prop, func(t *testing.T) {
   run(t, tt.module, tt.prop, tt.panicMsg)
  })
 }
}

func TestInvalidSingletonProvidersUsage(t *testing.T) {
 type singletonType struct {
  name     string
  factory  SingletonFactory
  parallel bool
 }

 run := func(t *testing.T, singletons []singletonType, panicMsg string) {
  t.Helper()
  ctx := NewContext()
  for _, s := range singletons {
   ctx.RegisterSingletonType(s.name, s.factory, s.parallel)
  }

  ctx.MockFileSystem(map[string][]byte{
   "Android.bp": {},
  })

  _, errs := ctx.ParseBlueprintsFiles("Android.bp", nil)

  if len(errs) == 0 {
   _, errs = ctx.ResolveDependencies(nil)
  }

  if len(errs) == 0 {
   _, errs = ctx.PrepareBuildActions(nil)
  }

  if len(panicMsg) == 0 {
   if len(errs) != 0 {
    t.Fatal("got an error: ", errs)
   }
   return
  }

  if len(errs) == 0 {
   t.Fatal("expected an error")
  }

  if len(errs) > 1 {
   t.Errorf("expected a single error, got %d:", len(errs))
   for i, err := range errs {
    t.Errorf("%d:  %s", i, err)
   }
   t.FailNow()
  }

  if panicErr, ok := errs[0].(panicError); ok {
   if panicErr.panic != panicMsg {
    t.Fatalf("expected panic %q, got %q", panicMsg, panicErr.panic)
   }
  } else {
   t.Fatalf("expected a panicError, got %T: %s", errs[0], errs[0].Error())
  }

 }

 tests := []struct {
  testName   string
  singletons []singletonType
  panicMsg   string
 }{
  {
   testName: "get_non_singleton_provider",
   singletons: []singletonType{
    {
     name: "parallel_singleton",
     factory: func() Singleton {
      return &providerTestParallelSingleton{}
     },
     parallel: true,
    },
    {
     name: "sequential_singleton",
     factory: func() Singleton {
      return &providerTestSequentialSingleton{
       getModuleProvider: true,
      }
     },
     parallel: false,
    },
   },
   panicMsg: "Can't get value of non-singleton provider *blueprint.providerTestMutatorInfo usign singleton specific get method",
  },
  {
   testName: "set_non_singleton_provider",
   singletons: []singletonType{
    {
     name: "sequential_singleton",
     factory: func() Singleton {
      return &providerTestSequentialSingleton{
       setModuleProvider: true,
      }
     },
     parallel: false,
    },
   },
   panicMsg: "Can't set value of non-singleton provider *blueprint.providerTestMutatorInfo inside singleton sequential_singleton",
  },
  {
   testName: "set_get_singleton_provider",
   singletons: []singletonType{
    {
     name: "parallel_singleton",
     factory: func() Singleton {
      return &providerTestParallelSingleton{}
     },
     parallel: true,
    },
    {
     name: "sequential_singleton",
     factory: func() Singleton {
      return &providerTestSequentialSingleton{}
     },
     parallel: false,
    },
   },
   panicMsg: "",
  },
  {
   testName: "visit_all_singletons_in_parallel_singleton",
   singletons: []singletonType{
    {
     name: "parallel_singleton",
     factory: func() Singleton {
      return &providerTestParallelSingleton{visitAllSingletons: true}
     },
     parallel: true,
    },
   },
   panicMsg: "VisitAllSingletons not allowed in parallel singletons parallel_singleton",
  },
 }

 for _, tt := range tests {
  t.Run(tt.testName, func(t *testing.T) {
   run(t, tt.singletons, tt.panicMsg)
  })
 }
}

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