aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configuration/CMakeLists.txt34
-rw-r--r--configuration/bazel/fruit/impl/fruit-config-base.h6
-rw-r--r--configuration/fruit-config-base.h.in4
-rw-r--r--include/fruit/component.h8
-rw-r--r--include/fruit/impl/component.defn.h17
-rw-r--r--include/fruit/impl/fruit-config.h10
-rw-r--r--tests/CMakeLists.txt2
-rw-r--r--tests/fruit_test_common.py77
-rw-r--r--tests/install_component_swap_optimization.cpp58
-rwxr-xr-xtests/test_binding_clash.py137
-rwxr-xr-xtests/test_install.py32
-rw-r--r--tests/test_install_component_swap_optimization.py65
-rwxr-xr-xtests/test_required_types.py2
13 files changed, 343 insertions, 109 deletions
diff --git a/configuration/CMakeLists.txt b/configuration/CMakeLists.txt
index e8a8407..3103e03 100644
--- a/configuration/CMakeLists.txt
+++ b/configuration/CMakeLists.txt
@@ -134,6 +134,36 @@ int main() {
"
FRUIT_HAS_FORCEINLINE)
+CHECK_CXX_SOURCE_COMPILES("
+[[deprecated]] void f() {
+}
+
+int main() {
+ return 0;
+}
+"
+FRUIT_HAS_ATTRIBUTE_DEPRECATED)
+
+CHECK_CXX_SOURCE_COMPILES("
+void f() __attribute__((deprecated)) {
+}
+
+int main() {
+ return 0;
+}
+"
+FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED)
+
+CHECK_CXX_SOURCE_COMPILES("
+__declspec(deprecated) void f() {
+}
+
+int main() {
+ return 0;
+}
+"
+FRUIT_HAS_DECLSPEC_DEPRECATED)
+
if (NOT "${FRUIT_HAS_STD_MAX_ALIGN_T}" AND NOT "${FRUIT_HAS_MAX_ALIGN_T}")
message(WARNING "The current C++ standard library doesn't support std::max_align_t nor ::max_align_t. Attempting to use std::max_align_t anyway, but it most likely won't work.")
endif()
@@ -143,6 +173,10 @@ if(NOT "${FRUIT_HAS_STD_IS_TRIVIALLY_COPYABLE}" AND NOT "${FRUIT_HAS_IS_TRIVIALL
message(WARNING "The current standard library doesn't support std::is_trivially_copyable<T>, and the current compiler doesn't support __is_trivially_copyable(T) nor __has_trivial_copy(T). Attemping to use std::is_trivially_copyable<T> anyway, but it most likely won't work.")
endif()
+if (NOT "${FRUIT_HAS_ATTRIBUTE_DEPRECATED}" AND NOT "${FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED}" AND NOT "${FRUIT_HAS_DECLSPEC_DEPRECATED}")
+ message(WARNING "No supported way to mark functions as deprecated was found. Continuing anyway, without the 'deprecated' markers.")
+endif()
+
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fruit-config-base.h.in ${CMAKE_CURRENT_BINARY_DIR}/../include/fruit/impl/fruit-config-base.h)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/../include/fruit/impl/fruit-config-base.h
diff --git a/configuration/bazel/fruit/impl/fruit-config-base.h b/configuration/bazel/fruit/impl/fruit-config-base.h
index 9cd392f..65b5261 100644
--- a/configuration/bazel/fruit/impl/fruit-config-base.h
+++ b/configuration/bazel/fruit/impl/fruit-config-base.h
@@ -57,4 +57,10 @@
#define FRUIT_HAS_FORCEINLINE 0
+#define FRUIT_HAS_ATTRIBUTE_DEPRECATED 0
+
+#define FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED 1
+
+#define FRUIT_HAS_DECLSPEC_DEPRECATED 0
+
#endif // FRUIT_CONFIG_BASE_H
diff --git a/configuration/fruit-config-base.h.in b/configuration/fruit-config-base.h.in
index c710a22..9f59195 100644
--- a/configuration/fruit-config-base.h.in
+++ b/configuration/fruit-config-base.h.in
@@ -30,5 +30,9 @@
#cmakedefine FRUIT_USES_BOOST 1
#cmakedefine FRUIT_HAS_ALWAYS_INLINE_ATTRIBUTE 1
#cmakedefine FRUIT_HAS_FORCEINLINE 1
+#cmakedefine FRUIT_HAS_ATTRIBUTE_DEPRECATED 1
+#cmakedefine FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED 1
+#cmakedefine FRUIT_HAS_DECLSPEC_DEPRECATED 1
+
#endif // FRUIT_CONFIG_BASE_H
diff --git a/include/fruit/component.h b/include/fruit/component.h
index a058db2..9e35907 100644
--- a/include/fruit/component.h
+++ b/include/fruit/component.h
@@ -68,6 +68,9 @@ class Component {
// Do not use. Use fruit::createComponent() instead.
Component() = default;
+ template<typename... Types>
+ friend class Component;
+
template<typename... Bindings>
friend
class PartialComponent;
@@ -481,7 +484,10 @@ class PartialComponent {
* As in the example, the template parameters will be inferred by the compiler, it's not necessary to specify them explicitly.
*/
template<typename... Params>
- PartialComponent<fruit::impl::OldStyleInstallComponent<Component<Params...>>, Bindings...> install(const Component<Params...>& component);
+ FRUIT_DEPRECATED(
+ PartialComponent<fruit::impl::OldStyleInstallComponent<Component<Params...>>, Bindings...>
+ install(const Component<Params...>& component)
+ );
/**
* Adds the bindings (and multibindings) in the Component obtained by calling fun(params...) to the current component.
diff --git a/include/fruit/impl/component.defn.h b/include/fruit/impl/component.defn.h
index fdd266e..2d1f01c 100644
--- a/include/fruit/impl/component.defn.h
+++ b/include/fruit/impl/component.defn.h
@@ -73,7 +73,22 @@ inline Component<Params...>::Component(PartialComponent<Bindings...> component)
template <typename... Params>
template <typename... OtherParams>
inline Component<Params...>::Component(Component<OtherParams...> component)
- : Component(fruit::createComponent().install(std::move(component))) {
+ : storage(std::move(component.storage)) {
+ (void)typename fruit::impl::meta::CheckIfError<Comp>::type();
+
+ using InstallBinding = fruit::impl::InstallComponent<Component<OtherParams...>>;
+
+ using Op1 = typename fruit::impl::meta::OpForComponent<>::template AddBinding<InstallBinding>;
+ (void)typename fruit::impl::meta::CheckIfError<Op1>::type();
+
+ using Op2 = typename fruit::impl::meta::OpForComponent<InstallBinding>::template ConvertTo<Comp>;
+ (void)typename fruit::impl::meta::CheckIfError<Op2>::type();
+
+ Op2()(storage);
+
+#ifndef FRUIT_NO_LOOP_CHECK
+ (void)typename fruit::impl::meta::CheckIfError<fruit::impl::meta::Eval<fruit::impl::meta::CheckNoLoopInDeps(typename Op2::Result)>>::type();
+#endif // !FRUIT_NO_LOOP_CHECK
}
template <typename... Bindings>
diff --git a/include/fruit/impl/fruit-config.h b/include/fruit/impl/fruit-config.h
index fc5a763..ec243ed 100644
--- a/include/fruit/impl/fruit-config.h
+++ b/include/fruit/impl/fruit-config.h
@@ -66,4 +66,14 @@
#define FRUIT_ALWAYS_INLINE
#endif
+#if FRUIT_HAS_ATTRIBUTE_DEPRECATED
+#define FRUIT_DEPRECATED(...) [[deprecated]] __VA_ARGS__
+#elif FRUIT_HAS_GCC_ATTRIBUTE_DEPRECATED
+#define FRUIT_DEPRECATED(...) __VA_ARGS__ __attribute__((deprecated))
+#elif FRUIT_HAS_DECLSPEC_DEPRECATED
+#define FRUIT_DEPRECATED(...) __declspec(deprecated) __VA_ARGS__
+#else
+#define FRUIT_DEPRECATED(...) __VA_ARGS__
+#endif
+
#endif // FRUIT_CONFIG_H
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 6da5ac2..bbf5e4c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -157,7 +157,6 @@ add_fruit_tests("root"
class_destruction.cpp
class_destruction_with_annotation.cpp
eager_injection.cpp
- install_component_swap_optimization.cpp
semistatic_map_hash_selection.cpp
test1.cpp
test1_old_style_install.cpp
@@ -218,6 +217,7 @@ add_pytest_based_fruit_tests("root"
"test_injector.py"
"test_injector_unsafe_get.py"
"test_install.py"
+ "test_install_component_swap_optimization.py"
"test_multibindings_bind_instance.py"
"test_multibindings_bind_interface.py"
"test_multibindings_bind_provider.py"
diff --git a/tests/fruit_test_common.py b/tests/fruit_test_common.py
index 72869e8..60deac2 100644
--- a/tests/fruit_test_common.py
+++ b/tests/fruit_test_common.py
@@ -75,13 +75,8 @@ class PosixCompiler:
def compile_discarding_output(self, source, include_dirs, args=[]):
try:
- self._compile(
- include_dirs,
- args = (
- args
- + ['-c', source]
- + ['-o', os.path.devnull]
- ))
+ args = args + ['-c', source, '-o', os.path.devnull]
+ self._compile(include_dirs, args=args)
except CommandFailedException as e:
raise CompilationFailedException(e.command, e.stderr)
@@ -105,6 +100,9 @@ class PosixCompiler:
)
run_command(self.executable, args)
+ def get_disable_deprecation_warning_flags(self):
+ return ['-Wno-deprecated-declarations']
+
class MsvcCompiler:
def __init__(self):
self.executable = CXX
@@ -112,12 +110,8 @@ class MsvcCompiler:
def compile_discarding_output(self, source, include_dirs, args=[]):
try:
- self._compile(
- include_dirs,
- args = (
- args
- + ['/c', source]
- ))
+ args = args + ['/c', source]
+ self._compile(include_dirs, args = args)
except CommandFailedException as e:
# Note that we use stdout here, unlike above. MSVC reports compilation warnings and errors on stdout.
raise CompilationFailedException(e.command, e.stdout)
@@ -141,6 +135,9 @@ class MsvcCompiler:
)
run_command(self.executable, args)
+ def get_disable_deprecation_warning_flags(self):
+ return ['/wd4996']
+
if CXX_COMPILER_NAME == 'MSVC':
compiler = MsvcCompiler()
if PATH_TO_COMPILED_FRUIT_LIB.endswith('.dll'):
@@ -200,13 +197,24 @@ def try_remove_temporary_file(filename):
# This shouldn't cause the tests to fail, so we ignore the exception and go ahead.
pass
-def expect_compile_error_helper(check_error_fun, setup_source_code, source_code, test_params={}):
+def expect_compile_error_helper(
+ check_error_fun,
+ setup_source_code,
+ source_code,
+ test_params={},
+ ignore_deprecation_warnings=False):
source_code = _construct_final_source_code(setup_source_code, source_code, test_params)
source_file_name = _create_temporary_file(source_code, file_name_suffix='.cpp')
try:
- compiler.compile_discarding_output(source=source_file_name, include_dirs=fruit_tests_include_dirs)
+ args = []
+ if ignore_deprecation_warnings:
+ args += compiler.get_disable_deprecation_warning_flags()
+ compiler.compile_discarding_output(
+ source=source_file_name,
+ include_dirs=fruit_tests_include_dirs,
+ args=args)
raise Exception('The test should have failed to compile, but it compiled successfully')
except CompilationFailedException as e1:
e = e1
@@ -255,7 +263,13 @@ def expect_generic_compile_error(expected_error_regex, setup_source_code, source
expect_compile_error_helper(check_error, setup_source_code, source_code, test_params)
-def expect_compile_error(expected_fruit_error_regex, expected_fruit_error_desc_regex, setup_source_code, source_code, test_params={}):
+def expect_compile_error(
+ expected_fruit_error_regex,
+ expected_fruit_error_desc_regex,
+ setup_source_code,
+ source_code,
+ test_params={},
+ ignore_deprecation_warnings=False):
"""
Tests that the given source produces the expected error during compilation.
@@ -271,6 +285,7 @@ def expect_compile_error(expected_fruit_error_regex, expected_fruit_error_desc_r
:param test_params: A dict containing the definition of some identifiers. Each identifier in
expected_fruit_error_regex and source_code will be replaced (textually) with its definition (if a definition
was provided).
+ :param ignore_deprecation_warnings: A boolean. If True, deprecation warnings will be ignored.
"""
if '\n' in expected_fruit_error_regex:
raise Exception('expected_fruit_error_regex should not contain newlines')
@@ -395,10 +410,15 @@ def expect_compile_error(expected_fruit_error_regex, expected_fruit_error_desc_r
raise Exception(
'The compilation failed with the expected message, but the error message contained some metaprogramming types in the output (besides Error). Error message:\n%s' + error_message_head)
- expect_compile_error_helper(check_error, setup_source_code, source_code, test_params)
+ expect_compile_error_helper(check_error, setup_source_code, source_code, test_params, ignore_deprecation_warnings)
-def expect_runtime_error(expected_error_regex, setup_source_code, source_code, test_params={}):
+def expect_runtime_error(
+ expected_error_regex,
+ setup_source_code,
+ source_code,
+ test_params={},
+ ignore_deprecation_warnings=False):
"""
Tests that the given source (compiles successfully and) produces the expected error at runtime.
@@ -421,9 +441,15 @@ def expect_runtime_error(expected_error_regex, setup_source_code, source_code, t
source_file_name = _create_temporary_file(source_code, file_name_suffix='.cpp')
executable_suffix = {'posix': '', 'nt': '.exe'}[os.name]
output_file_name = _create_temporary_file('', executable_suffix)
+
+ args = fruit_tests_linker_flags
+ if ignore_deprecation_warnings:
+ args += compiler.get_disable_deprecation_warning_flags()
compiler.compile_and_link(
- source=source_file_name, include_dirs=fruit_tests_include_dirs, output_file_name=output_file_name,
- args=fruit_tests_linker_flags)
+ source=source_file_name,
+ include_dirs=fruit_tests_include_dirs,
+ output_file_name=output_file_name,
+ args=args)
try:
run_command(output_file_name)
@@ -451,7 +477,7 @@ def expect_runtime_error(expected_error_regex, setup_source_code, source_code, t
try_remove_temporary_file(output_file_name)
-def expect_success(setup_source_code, source_code, test_params={}):
+def expect_success(setup_source_code, source_code, test_params={}, ignore_deprecation_warnings=False):
"""
Tests that the given source compiles and runs successfully.
@@ -474,9 +500,14 @@ def expect_success(setup_source_code, source_code, test_params={}):
executable_suffix = {'posix': '', 'nt': '.exe'}[os.name]
output_file_name = _create_temporary_file('', executable_suffix)
+ args = fruit_tests_linker_flags
+ if ignore_deprecation_warnings:
+ args += compiler.get_disable_deprecation_warning_flags()
compiler.compile_and_link(
- source=source_file_name, include_dirs=fruit_tests_include_dirs, output_file_name=output_file_name,
- args=fruit_tests_linker_flags)
+ source=source_file_name,
+ include_dirs=fruit_tests_include_dirs,
+ output_file_name=output_file_name,
+ args=args)
if RUN_TESTS_UNDER_VALGRIND.lower() in ('false', 'off', 'no', '0', ''):
run_command(output_file_name)
diff --git a/tests/install_component_swap_optimization.cpp b/tests/install_component_swap_optimization.cpp
deleted file mode 100644
index 7faece9..0000000
--- a/tests/install_component_swap_optimization.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2014 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.
- */
-
-#include "test_common.h"
-
-using namespace std;
-
-fruit::Component<int, float, double, unsigned> getParentComponent() {
- static int x = 0;
- static float y = 0;
- static double z = 0;
- static unsigned u = 0;
- return fruit::createComponent()
- .bindInstance(x)
- .bindInstance(y)
- .bindInstance(z)
- .bindInstance(u);
-}
-
-fruit::Component<vector<int>, vector<float>, vector<double>, vector<unsigned>> getParentComponent2() {
- static vector<int> x;
- static vector<float> y;
- static vector<double> z;
- static vector<unsigned> u;
- return fruit::createComponent()
- .bindInstance(x)
- .bindInstance(y)
- .bindInstance(z)
- .bindInstance(u)
- .addInstanceMultibinding(x);
-}
-
-fruit::Component<int, float, double, unsigned> getComponent() {
- return fruit::createComponent()
- .install(getParentComponent())
- .install(getParentComponent2());
-}
-
-int main() {
- fruit::Injector<int, float, double, unsigned> injector(getComponent());
-
- injector.get<int>();
-
- return 0;
-}
diff --git a/tests/test_binding_clash.py b/tests/test_binding_clash.py
index 666177c..0675777 100755
--- a/tests/test_binding_clash.py
+++ b/tests/test_binding_clash.py
@@ -97,8 +97,6 @@ OLD_STYLE_INSTALL2=(
INTERFACE_BINDING + INTERFACE_BINDING2,
INSTALL + CONSTRUCTOR_BINDING,
INSTALL + INTERFACE_BINDING,
- OLD_STYLE_INSTALL + CONSTRUCTOR_BINDING,
- OLD_STYLE_INSTALL + INTERFACE_BINDING,
],
ids= [
'CONSTRUCTOR_BINDING + CONSTRUCTOR_BINDING',
@@ -107,8 +105,6 @@ OLD_STYLE_INSTALL2=(
'INTERFACE_BINDING + INTERFACE_BINDING2',
'INSTALL + CONSTRUCTOR_BINDING',
'INSTALL + INTERFACE_BINDING',
- 'OLD_STYLE_INSTALL + CONSTRUCTOR_BINDING',
- 'OLD_STYLE_INSTALL + INTERFACE_BINDING',
])
@pytest.mark.parametrize('XAnnot,YAnnot,Y2Annot', [
('X', 'Y', 'Y2'),
@@ -138,9 +134,80 @@ def test_clash_with_binding(binding1_preparation, binding1, binding2_preparation
@pytest.mark.parametrize(
'binding1_preparation,binding1,binding2_preparation,binding2',
[
+ OLD_STYLE_INSTALL + CONSTRUCTOR_BINDING,
+ OLD_STYLE_INSTALL + INTERFACE_BINDING,
+ ],
+ ids= [
+ 'OLD_STYLE_INSTALL + CONSTRUCTOR_BINDING',
+ 'OLD_STYLE_INSTALL + INTERFACE_BINDING',
+ ])
+@pytest.mark.parametrize('XAnnot,YAnnot,Y2Annot', [
+ ('X', 'Y', 'Y2'),
+ ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>', 'fruit::Annotated<Annotation3, Y2>'),
+])
+def test_clash_with_binding_old_style_install(
+ binding1_preparation, binding1, binding2_preparation, binding2, XAnnot, YAnnot, Y2Annot):
+ source = '''
+ struct X{};
+
+ %s
+ %s
+
+ fruit::Component<XAnnot> getComponent() {
+ return fruit::createComponent()
+ %s
+ %s;
+ }
+
+ ''' % (binding1_preparation, binding2_preparation, binding1, binding2)
+ expect_compile_error(
+ 'TypeAlreadyBoundError<XAnnot>',
+ 'Trying to bind C but it is already bound.',
+ COMMON_DEFINITIONS,
+ source,
+ locals(),
+ ignore_deprecation_warnings=True)
+
+@pytest.mark.parametrize(
+ 'binding1_preparation,binding1,binding2_preparation,binding2',
+ [
CONSTRUCTOR_BINDING + INSTALL,
INTERFACE_BINDING + INSTALL,
INSTALL + INSTALL2,
+ ],
+ ids = [
+ 'CONSTRUCTOR_BINDING + INSTALL',
+ 'INTERFACE_BINDING + INSTALL',
+ 'INSTALL + INSTALL2',
+ ])
+@pytest.mark.parametrize('XAnnot,YAnnot,Y2Annot', [
+ ('X', 'Y', 'Y2'),
+ ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>', 'fruit::Annotated<Annotation3, Y2>'),
+])
+def test_clash_with_install(
+ binding1_preparation, binding1, binding2_preparation, binding2, XAnnot, YAnnot, Y2Annot):
+ source = '''
+ struct X{};
+
+ %s
+ %s
+
+ fruit::Component<XAnnot> getComponent() {
+ return fruit::createComponent()
+ %s
+ %s;
+ }
+ ''' % (binding1_preparation, binding2_preparation, binding1, binding2)
+ expect_compile_error(
+ 'DuplicateTypesInComponentError<XAnnot>',
+ 'The installed component provides some types that are already provided by the current component.',
+ COMMON_DEFINITIONS,
+ source,
+ locals())
+
+@pytest.mark.parametrize(
+ 'binding1_preparation,binding1,binding2_preparation,binding2',
+ [
CONSTRUCTOR_BINDING + OLD_STYLE_INSTALL,
INTERFACE_BINDING + OLD_STYLE_INSTALL,
OLD_STYLE_INSTALL + OLD_STYLE_INSTALL2,
@@ -148,9 +215,6 @@ def test_clash_with_binding(binding1_preparation, binding1, binding2_preparation
OLD_STYLE_INSTALL + INSTALL2,
],
ids = [
- 'CONSTRUCTOR_BINDING + INSTALL',
- 'INTERFACE_BINDING + INSTALL',
- 'INSTALL + INSTALL2',
'CONSTRUCTOR_BINDING + OLD_STYLE_INSTALL',
'INTERFACE_BINDING + OLD_STYLE_INSTALL',
'OLD_STYLE_INSTALL + OLD_STYLE_INSTALL2',
@@ -161,7 +225,7 @@ def test_clash_with_binding(binding1_preparation, binding1, binding2_preparation
('X', 'Y', 'Y2'),
('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>', 'fruit::Annotated<Annotation3, Y2>'),
])
-def test_clash_with_install(
+def test_clash_with_install_old_style_install(
binding1_preparation, binding1, binding2_preparation, binding2, XAnnot, YAnnot, Y2Annot):
source = '''
struct X{};
@@ -180,7 +244,8 @@ def test_clash_with_install(
'The installed component provides some types that are already provided by the current component.',
COMMON_DEFINITIONS,
source,
- locals())
+ locals(),
+ ignore_deprecation_warnings=True)
CONSTRUCTOR_BINDING_ANNOT1=(
'',
@@ -246,16 +311,9 @@ OLD_STYLE_INSTALL_ANNOT2=(
INTERFACE_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2,
INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2,
- OLD_STYLE_INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
- OLD_STYLE_INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2,
CONSTRUCTOR_BINDING_ANNOT1 + INSTALL_ANNOT2,
INTERFACE_BINDING_ANNOT1 + INSTALL_ANNOT2,
- CONSTRUCTOR_BINDING_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
- INTERFACE_BINDING_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
INSTALL_ANNOT1 + INSTALL_ANNOT2,
- OLD_STYLE_INSTALL_ANNOT1 + INSTALL_ANNOT2,
- INSTALL_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
- OLD_STYLE_INSTALL_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
],
ids=[
'CONSTRUCTOR_BINDING_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',
@@ -264,18 +322,54 @@ OLD_STYLE_INSTALL_ANNOT2=(
'INTERFACE_BINDING_ANNOT1 + INTERFACE_BINDING_ANNOT2',
'INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',
'INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2',
- 'OLD_STYLE_INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',
- 'OLD_STYLE_INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2',
'CONSTRUCTOR_BINDING_ANNOT1 + INSTALL_ANNOT2',
'INTERFACE_BINDING_ANNOT1 + INSTALL_ANNOT2',
+ 'INSTALL_ANNOT1 + INSTALL_ANNOT2',
+ ])
+def test_no_clash_with_different_annotations(binding1_preparation, binding1, binding2_preparation, binding2):
+ source = '''
+ struct X {};
+
+ %s
+ %s
+
+ fruit::Component<XAnnot1, XAnnot2> getComponent() {
+ return fruit::createComponent()
+ %s
+ %s;
+ }
+
+ int main() {
+ fruit::Injector<XAnnot1, XAnnot2> injector(getComponent());
+ injector.get<XAnnot1>();
+ injector.get<XAnnot2>();
+ }
+ ''' % (binding1_preparation, binding2_preparation, binding1, binding2)
+ expect_success(
+ COMMON_DEFINITIONS,
+ source)
+
+@pytest.mark.parametrize(
+ 'binding1_preparation,binding1,binding2_preparation,binding2',
+ [
+ OLD_STYLE_INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2,
+ OLD_STYLE_INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2,
+ CONSTRUCTOR_BINDING_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
+ INTERFACE_BINDING_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
+ OLD_STYLE_INSTALL_ANNOT1 + INSTALL_ANNOT2,
+ INSTALL_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
+ OLD_STYLE_INSTALL_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2,
+ ],
+ ids=[
+ 'OLD_STYLE_INSTALL_ANNOT1 + CONSTRUCTOR_BINDING_ANNOT2',
+ 'OLD_STYLE_INSTALL_ANNOT1 + INTERFACE_BINDING_ANNOT2',
'CONSTRUCTOR_BINDING_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2',
'INTERFACE_BINDING_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2',
- 'INSTALL_ANNOT1 + INSTALL_ANNOT2',
'OLD_STYLE_INSTALL_ANNOT1 + INSTALL_ANNOT2',
'INSTALL_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2',
'OLD_STYLE_INSTALL_ANNOT1 + OLD_STYLE_INSTALL_ANNOT2',
])
-def test_no_clash_with_different_annotations(binding1_preparation, binding1, binding2_preparation, binding2):
+def test_no_clash_with_different_annotations_old_style_install(binding1_preparation, binding1, binding2_preparation, binding2):
source = '''
struct X {};
@@ -296,7 +390,8 @@ def test_no_clash_with_different_annotations(binding1_preparation, binding1, bin
''' % (binding1_preparation, binding2_preparation, binding1, binding2)
expect_success(
COMMON_DEFINITIONS,
- source)
+ source,
+ ignore_deprecation_warnings=True)
@pytest.mark.parametrize('XAnnot', [
'X',
diff --git a/tests/test_install.py b/tests/test_install.py
index 9baf807..42bec54 100755
--- a/tests/test_install.py
+++ b/tests/test_install.py
@@ -72,7 +72,32 @@ def test_success_old_style():
Assert(x.n == 5);
}
'''
- expect_success(COMMON_DEFINITIONS, source)
+ expect_success(COMMON_DEFINITIONS, source, ignore_deprecation_warnings=True)
+
+def test_old_style_deprecation_error():
+ source = '''
+ struct X {
+ int n;
+ X(int n) : n(n) {}
+ };
+
+ fruit::Component<X> getParentComponent() {
+ return fruit::createComponent()
+ .registerProvider([]() { return X(5); });
+ }
+
+ fruit::Component<X> getComponent() {
+ return fruit::createComponent()
+ .install(getParentComponent());
+ }
+
+ int main() {
+ fruit::Injector<X> injector(getComponent());
+ X x = injector.get<X>();
+ Assert(x.n == 5);
+ }
+ '''
+ expect_generic_compile_error('deprecation|deprecated', COMMON_DEFINITIONS, source)
def test_with_requirements_success():
source = '''
@@ -144,7 +169,7 @@ def test_with_requirements_success_old_style():
Assert(y.x.n == 5);
}
'''
- expect_success(COMMON_DEFINITIONS, source)
+ expect_success(COMMON_DEFINITIONS, source, ignore_deprecation_warnings=True)
def test_with_requirements_not_specified_in_child_component_error():
source = '''
@@ -202,7 +227,8 @@ def test_with_requirements_not_specified_in_child_component_error_old_style():
'NoBindingFoundError<X>',
'No explicit binding nor C::Inject definition was found for T',
COMMON_DEFINITIONS,
- source)
+ source,
+ ignore_deprecation_warnings=True)
def test_install_with_args_success():
source = '''
diff --git a/tests/test_install_component_swap_optimization.py b/tests/test_install_component_swap_optimization.py
new file mode 100644
index 0000000..12bd643
--- /dev/null
+++ b/tests/test_install_component_swap_optimization.py
@@ -0,0 +1,65 @@
+#!/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 fruit_test_common import *
+
+COMMON_DEFINITIONS = '''
+ #include "test_common.h"
+ '''
+
+def test_install_component_swap_optimization():
+ source = '''
+ fruit::Component<int, float, double, unsigned> getParentComponent() {
+ static int x = 0;
+ static float y = 0;
+ static double z = 0;
+ static unsigned u = 0;
+ return fruit::createComponent()
+ .bindInstance(x)
+ .bindInstance(y)
+ .bindInstance(z)
+ .bindInstance(u);
+ }
+
+ fruit::Component<std::vector<int>, std::vector<float>, std::vector<double>, std::vector<unsigned>> getParentComponent2() {
+ static std::vector<int> x;
+ static std::vector<float> y;
+ static std::vector<double> z;
+ static std::vector<unsigned> u;
+ return fruit::createComponent()
+ .bindInstance(x)
+ .bindInstance(y)
+ .bindInstance(z)
+ .bindInstance(u)
+ .addInstanceMultibinding(x);
+ }
+
+ fruit::Component<int, float, double, unsigned> getComponent() {
+ return fruit::createComponent()
+ .install(getParentComponent())
+ .install(getParentComponent2());
+ }
+
+ int main() {
+ fruit::Injector<int, float, double, unsigned> injector(getComponent());
+ injector.get<int>();
+
+ return 0;
+ }
+ '''
+ expect_success(COMMON_DEFINITIONS, source, ignore_deprecation_warnings=True)
+
+if __name__== '__main__':
+ main(__file__)
diff --git a/tests/test_required_types.py b/tests/test_required_types.py
index 190461c..8ca8a60 100755
--- a/tests/test_required_types.py
+++ b/tests/test_required_types.py
@@ -104,7 +104,7 @@ def test_required_success_old_style_install():
y->doStuff();
}
'''
- expect_success(COMMON_DEFINITIONS, source)
+ expect_success(COMMON_DEFINITIONS, source, ignore_deprecation_warnings=True)
def test_required_annotated_success():
source = '''