978 lines
40 KiB
Python
Executable File
978 lines
40 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright 2016 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.
|
|
|
|
from absl.testing import parameterized
|
|
from fruit_test_common import *
|
|
|
|
COMMON_DEFINITIONS = '''
|
|
#include "test_common.h"
|
|
|
|
'''
|
|
|
|
class TestComponentReplacement(parameterized.TestCase):
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_success(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_success_across_normalized_component(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent1() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent2() {
|
|
return fruit::createComponent()
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::NormalizedComponent<> normalizedComponent(getRootComponent1);
|
|
fruit::Injector<int> injector(normalizedComponent, getRootComponent2);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_installed_using_component_function_success(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.installComponentFunctions(fruit::componentFunction(ReplacedComponentInstallation));
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
def test_replace_component_success_with_conversion(self):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(std::string) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(double, std::string, int) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(getReplacedComponent, "Hi").with(getReplacementComponent, 2.0, "Hello", 12)
|
|
.install(getReplacedComponent, "Hi");
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
def test_replace_component_installed_using_component_function_success_with_conversion(self):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(std::string) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(double, std::string, int) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(getReplacedComponent, "Hi").with(getReplacementComponent, 2.0, "Hello", 12)
|
|
.installComponentFunctions(fruit::componentFunction(getReplacedComponent, "Hi"));
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent', 'getReplacementComponent', 'getReplacementReplacementComponent'),
|
|
('double', 'getReplacedComponent, 1.0', 'getReplacementComponent, 1.0', 'getReplacementReplacementComponent, 1.0'),
|
|
])
|
|
def test_replace_component_chain_success(self,
|
|
ComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentInstallation, ReplacementReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementReplacementComponent(ComponentParamTypes) {
|
|
static int n = 30;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.replace(ReplacementComponentInstallation).with(ReplacementReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 30);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent', 'getReplacementComponent', 'getReplacementReplacementComponent'),
|
|
('double', 'getReplacedComponent, 1.0', 'getReplacementComponent, 1.0', 'getReplacementReplacementComponent, 1.0'),
|
|
])
|
|
def test_replace_component_chain_other_order_success(self,
|
|
ComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentInstallation, ReplacementReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementReplacementComponent(ComponentParamTypes) {
|
|
static int n = 30;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacementComponentInstallation).with(ReplacementReplacementComponentInstallation)
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 30);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
def test_replace_component_different_type_error(self):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent();
|
|
fruit::Component<double> getReplacementComponent();
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(getReplacedComponent).with(getReplacementComponent);
|
|
}
|
|
'''
|
|
expect_generic_compile_error(
|
|
# Clang
|
|
r'candidate template ignored: could not match .Component<int>. against .Component<double>.'
|
|
# GCC
|
|
r'|mismatched types .int. and .double.'
|
|
# MSVC
|
|
r'|could not deduce template argument for .fruit::Component<int> \(__cdecl \*\)\(FormalArgs...\). from .fruit::Component<double> \(void\).',
|
|
COMMON_DEFINITIONS,
|
|
source)
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_already_replaced_consistent_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_already_replaced_across_normalized_component_consistent_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent1() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent2() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::NormalizedComponent<> normalizedComponent(getRootComponent1);
|
|
fruit::Injector<int> injector(normalizedComponent, getRootComponent2);
|
|
int n = injector.get<int>();
|
|
Assert(n == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent', 'getOtherReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")', 'getOtherReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_already_replaced_inconsistent_error(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation, OtherReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getOtherReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 30;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.replace(ReplacedComponentInstallation).with(OtherReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
(void) injector;
|
|
}
|
|
'''
|
|
expect_runtime_error(
|
|
r'Fatal injection error: the component function at (0x)?[0-9a-fA-F]* with signature '
|
|
r'(class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) was replaced '
|
|
r'\(using .replace\(...\).with\(...\)\) with both the component function at (0x)?[0-9a-fA-F]* with signature '
|
|
r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) and the component function at '
|
|
r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) .',
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent', 'getOtherReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")', 'getOtherReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_already_replaced_across_normalized_component_inconsistent_error(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation, OtherReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getOtherReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 30;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent1() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent2() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(OtherReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::NormalizedComponent<> normalizedComponent(getRootComponent1);
|
|
fruit::Injector<> injector(normalizedComponent, getRootComponent2);
|
|
(void) injector;
|
|
}
|
|
'''
|
|
expect_runtime_error(
|
|
r'Fatal injection error: the component function at (0x)?[0-9a-fA-F]* with signature '
|
|
r'(class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) was replaced '
|
|
r'\(using .replace\(...\).with\(...\)\) with both the component function at (0x)?[0-9a-fA-F]* with signature '
|
|
r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) and the component function at '
|
|
r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) .',
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_after_install_error(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.install(ReplacedComponentInstallation)
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<int> injector(getRootComponent);
|
|
(void) injector;
|
|
}
|
|
'''
|
|
expect_runtime_error(
|
|
r'Fatal injection error: unable to replace \(using .replace\(...\).with\(...\)\) the component function at '
|
|
r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) with the '
|
|
r'component function at (0x)?[0-9a-fA-F]* with signature '
|
|
r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) because the former component function '
|
|
r'was installed before the .replace\(...\).with\(...\).',
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_after_install_across_normalized_component_error(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<int> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.bindInstance(n);
|
|
}
|
|
|
|
fruit::Component<int> getRootComponent1() {
|
|
return fruit::createComponent()
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent2() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::NormalizedComponent<int> normalizedComponent(getRootComponent1);
|
|
fruit::Injector<int> injector(normalizedComponent, getRootComponent2);
|
|
(void) injector;
|
|
}
|
|
'''
|
|
expect_runtime_error(
|
|
r'Fatal injection error: unable to replace \(using .replace\(...\).with\(...\)\) the component function at '
|
|
r'(0x)?[0-9a-fA-F]* with signature (class )?fruit::Component<int> \((__cdecl)?\*\)\((void)?ReplacedComponentParamTypes\) with the '
|
|
r'component function at (0x)?[0-9a-fA-F]* with signature '
|
|
r'(class )?fruit::Component<int> \((__cdecl)?\*\)\(.*\) because the former component function '
|
|
r'was installed before the .replace\(...\).with\(...\).',
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@parameterized.parameters([
|
|
('', 'getReplacedComponent', '', 'getReplacementComponent'),
|
|
('double', 'getReplacedComponent, 1.0', 'std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_unused_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 0);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_used_multiple_times_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 1);
|
|
Assert(*(multibindings[0]) == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_also_installed_directly_before_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.install(ReplacementComponentInstallation)
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 1);
|
|
Assert(*(multibindings[0]) == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_also_installed_directly_after_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation)
|
|
.install(ReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 1);
|
|
Assert(*(multibindings[0]) == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_also_installed_directly_before_across_normalized_component_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent1() {
|
|
return fruit::createComponent()
|
|
.install(ReplacementComponentInstallation);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent2() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::NormalizedComponent<> normalizedComponent(getRootComponent1);
|
|
fruit::Injector<> injector(normalizedComponent, getRootComponent2);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 1);
|
|
Assert(*(multibindings[0]) == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent'),
|
|
('double', 'getReplacedComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_component_also_installed_directly_after_across_normalized_component_ok(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent1() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent2() {
|
|
return fruit::createComponent()
|
|
.install(ReplacementComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::NormalizedComponent<> normalizedComponent(getRootComponent1);
|
|
fruit::Injector<> injector(normalizedComponent, getRootComponent2);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 1);
|
|
Assert(*(multibindings[0]) == 20);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
@multiple_parameters([
|
|
('', 'getReplacedComponent', 'getOtherReplacementComponent'),
|
|
('double', 'getReplacedComponent, 1.0', 'getOtherReplacementComponent, 1.0'),
|
|
], [
|
|
('', 'getReplacementComponent'),
|
|
('std::string', 'getReplacementComponent, std::string("Hello, world")'),
|
|
])
|
|
def test_replace_multiple_components_with_same(self,
|
|
ReplacedComponentParamTypes, ReplacedComponentInstallation, OtherReplacedComponentInstallation, ReplacementComponentParamTypes, ReplacementComponentInstallation):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(ReplacedComponentParamTypes) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getOtherReplacementComponent(ReplacedComponentParamTypes) {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent(ReplacementComponentParamTypes) {
|
|
static int n = 30;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(ReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.replace(OtherReplacedComponentInstallation).with(ReplacementComponentInstallation)
|
|
.install(ReplacedComponentInstallation)
|
|
.install(OtherReplacedComponentInstallation);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 1);
|
|
Assert(*(multibindings[0]) == 30);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
def test_replace_component_one_set_of_args_only(self):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(double) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent() {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(getReplacedComponent, 1.0).with(getReplacementComponent)
|
|
.install(getReplacedComponent, 1.0)
|
|
.install(getReplacedComponent, 5.0);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 2);
|
|
Assert(*(multibindings[0]) == 20);
|
|
Assert(*(multibindings[1]) == 10);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
def test_replace_component_already_replaced_with_different_args(self):
|
|
source = '''
|
|
fruit::Component<> getReplacedComponent(double) {
|
|
static int n = 10;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getReplacementComponent() {
|
|
static int n = 20;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getOtherReplacementComponent() {
|
|
static int n = 30;
|
|
return fruit::createComponent()
|
|
.addInstanceMultibinding(n);
|
|
}
|
|
|
|
fruit::Component<> getRootComponent() {
|
|
return fruit::createComponent()
|
|
.replace(getReplacedComponent, 1.0).with(getReplacementComponent)
|
|
.replace(getReplacedComponent, 5.0).with(getOtherReplacementComponent)
|
|
.install(getReplacedComponent, 1.0)
|
|
.install(getReplacedComponent, 5.0);
|
|
}
|
|
|
|
int main() {
|
|
fruit::Injector<> injector(getRootComponent);
|
|
|
|
std::vector<int*> multibindings = injector.getMultibindings<int>();
|
|
Assert(multibindings.size() == 2);
|
|
Assert(*(multibindings[0]) == 20);
|
|
Assert(*(multibindings[1]) == 30);
|
|
}
|
|
'''
|
|
expect_success(
|
|
COMMON_DEFINITIONS,
|
|
source,
|
|
locals())
|
|
|
|
if __name__ == '__main__':
|
|
absltest.main()
|