Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adf1b2a2 authored by Liz Kammer's avatar Liz Kammer Committed by Gerrit Code Review
Browse files

Merge "Add SetProperties to json-module-graph"

parents e844132b 9525e710
Loading
Loading
Loading
Loading
+59 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import (
	"os"
	"path"
	"path/filepath"
	"reflect"
	"regexp"
	"strings"
	"text/scanner"
@@ -1326,7 +1327,64 @@ func (m *ModuleBase) GetUnconvertedBp2buildDeps() []string {
}

func (m *ModuleBase) AddJSONData(d *map[string]interface{}) {
	(*d)["Android"] = map[string]interface{}{}
	(*d)["Android"] = map[string]interface{}{
		// Properties set in Blueprint or in blueprint of a defaults modules
		"SetProperties": m.propertiesWithValues(),
	}
}

type propInfo struct {
	Name string
	Type string
}

func (m *ModuleBase) propertiesWithValues() []propInfo {
	var info []propInfo
	props := m.GetProperties()

	var propsWithValues func(name string, v reflect.Value)
	propsWithValues = func(name string, v reflect.Value) {
		kind := v.Kind()
		switch kind {
		case reflect.Ptr, reflect.Interface:
			if v.IsNil() {
				return
			}
			propsWithValues(name, v.Elem())
		case reflect.Struct:
			if v.IsZero() {
				return
			}
			for i := 0; i < v.NumField(); i++ {
				namePrefix := name
				sTyp := v.Type().Field(i)
				if proptools.ShouldSkipProperty(sTyp) {
					continue
				}
				if name != "" && !strings.HasSuffix(namePrefix, ".") {
					namePrefix += "."
				}
				if !proptools.IsEmbedded(sTyp) {
					namePrefix += sTyp.Name
				}
				sVal := v.Field(i)
				propsWithValues(namePrefix, sVal)
			}
		case reflect.Array, reflect.Slice:
			if v.IsNil() {
				return
			}
			elKind := v.Type().Elem().Kind()
			info = append(info, propInfo{name, elKind.String() + " " + kind.String()})
		default:
			info = append(info, propInfo{name, kind.String()})
		}
	}

	for _, p := range props {
		propsWithValues("", reflect.ValueOf(p).Elem())
	}
	return info
}

func (m *ModuleBase) ComponentDepsMutator(BottomUpMutatorContext) {}
+201 −0
Original line number Diff line number Diff line
@@ -615,3 +615,204 @@ func parseMkRules(t *testing.T, config Config, nodes []mkparser.Node) []installM

	return rules
}

type PropsTestModuleEmbedded struct {
	Embedded_prop *string
}

type propsTestModule struct {
	ModuleBase
	DefaultableModuleBase
	props struct {
		A string `android:"arch_variant"`
		B *bool
		C []string
	}
	otherProps struct {
		PropsTestModuleEmbedded

		D      *int64
		Nested struct {
			E *string
		}
		F *string `blueprint:"mutated"`
	}
}

func propsTestModuleFactory() Module {
	module := &propsTestModule{}
	module.AddProperties(&module.props, &module.otherProps)
	InitAndroidArchModule(module, HostAndDeviceSupported, MultilibBoth)
	InitDefaultableModule(module)
	return module
}

type propsTestModuleDefaults struct {
	ModuleBase
	DefaultsModuleBase
}

func propsTestModuleDefaultsFactory() Module {
	defaults := &propsTestModuleDefaults{}
	module := propsTestModule{}
	defaults.AddProperties(&module.props, &module.otherProps)
	InitDefaultsModule(defaults)
	return defaults
}

func (p *propsTestModule) GenerateAndroidBuildActions(ctx ModuleContext) {
	str := "abc"
	p.otherProps.F = &str
}

func TestUsedProperties(t *testing.T) {
	testCases := []struct {
		desc          string
		bp            string
		expectedProps []propInfo
	}{
		{
			desc: "only name",
			bp: `test {
			name: "foo",
		}
	`,
			expectedProps: []propInfo{
				propInfo{"Name", "string"},
			},
		},
		{
			desc: "some props",
			bp: `test {
			name: "foo",
			a: "abc",
			b: true,
			d: 123,
		}
	`,
			expectedProps: []propInfo{
				propInfo{"A", "string"},
				propInfo{"B", "bool"},
				propInfo{"D", "int64"},
				propInfo{"Name", "string"},
			},
		},
		{
			desc: "unused non-pointer prop",
			bp: `test {
			name: "foo",
			b: true,
			d: 123,
		}
	`,
			expectedProps: []propInfo{
				// for non-pointer cannot distinguish between unused and intentionally set to empty
				propInfo{"A", "string"},
				propInfo{"B", "bool"},
				propInfo{"D", "int64"},
				propInfo{"Name", "string"},
			},
		},
		{
			desc: "nested props",
			bp: `test {
			name: "foo",
			nested: {
				e: "abc",
			}
		}
	`,
			expectedProps: []propInfo{
				propInfo{"Nested.E", "string"},
				propInfo{"Name", "string"},
			},
		},
		{
			desc: "arch props",
			bp: `test {
			name: "foo",
			arch: {
				x86_64: {
					a: "abc",
				},
			}
		}
	`,
			expectedProps: []propInfo{
				propInfo{"Name", "string"},
				propInfo{"Arch.X86_64.A", "string"},
			},
		},
		{
			desc: "embedded props",
			bp: `test {
			name: "foo",
			embedded_prop: "a",
		}
	`,
			expectedProps: []propInfo{
				propInfo{"Embedded_prop", "string"},
				propInfo{"Name", "string"},
			},
		},
		{
			desc: "defaults",
			bp: `
test_defaults {
	name: "foo_defaults",
	a: "a",
	b: true,
	embedded_prop:"a",
	arch: {
		x86_64: {
			a: "a",
		},
	},
}
test {
	name: "foo",
	defaults: ["foo_defaults"],
	c: ["a"],
	nested: {
		e: "d",
	},
	target: {
		linux: {
			a: "a",
		},
	},
}
	`,
			expectedProps: []propInfo{
				propInfo{"A", "string"},
				propInfo{"B", "bool"},
				propInfo{"C", "string slice"},
				propInfo{"Embedded_prop", "string"},
				propInfo{"Nested.E", "string"},
				propInfo{"Name", "string"},
				propInfo{"Arch.X86_64.A", "string"},
				propInfo{"Target.Linux.A", "string"},
				propInfo{"Defaults", "string slice"},
			},
		},
	}

	for _, tc := range testCases {
		t.Run(tc.desc, func(t *testing.T) {
			result := GroupFixturePreparers(
				PrepareForTestWithAllowMissingDependencies,
				PrepareForTestWithDefaults,
				FixtureRegisterWithContext(func(ctx RegistrationContext) {
					ctx.RegisterModuleType("test", propsTestModuleFactory)
					ctx.RegisterModuleType("test_defaults", propsTestModuleDefaultsFactory)
				}),
				FixtureWithRootAndroidBp(tc.bp),
			).RunTest(t)

			foo := result.ModuleForTests("foo", "").Module().base()

			AssertDeepEquals(t, "foo ", tc.expectedProps, foo.propertiesWithValues())

		})
	}
}
+7 −10
Original line number Diff line number Diff line
@@ -244,17 +244,14 @@ func TestAddJSONData(t *testing.T) {
	}
	jsonData := map[string]interface{}{}
	prebuiltStubsSources.AddJSONData(&jsonData)
	if fmt.Sprint(jsonData) != fmt.Sprint(
		map[string]interface{}{
			"Android": map[string]interface{}{},
			"Actions": []map[string]interface{}{
	expectedOut := []map[string]interface{}{
		map[string]interface{}{
			"Inputs":  []string{},
			"Outputs": []string{},
		},
			},
		}) {
		t.Errorf("The JSON data map isn't as expected %s.", jsonData)
	}
	if !reflect.DeepEqual(jsonData["Actions"], expectedOut) {
		t.Errorf("The JSON action data %#v isn't as expected %#v.", jsonData["Actions"], expectedOut)
	}
}