1#!/usr/bin/env python3 2# Copyright 2016 Google Inc. All Rights Reserved. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS-IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15 16from absl.testing import parameterized 17from fruit_test_common import * 18 19COMMON_DEFINITIONS = ''' 20 #include "test_common.h" 21 22 struct X; 23 24 struct Annotation1 {}; 25 using XAnnot1 = fruit::Annotated<Annotation1, X>; 26 27 struct Annotation2 {}; 28 using XAnnot2 = fruit::Annotated<Annotation2, X>; 29 ''' 30 31class TestNormalizedComponent(parameterized.TestCase): 32 @parameterized.parameters([ 33 ('X', 'X', 'Y'), 34 ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, X)', 'fruit::Annotated<Annotation2, Y>'), 35 ]) 36 def test_success_normalized_component_provides_unused(self, XAnnot, X_ANNOT, YAnnot): 37 source = ''' 38 struct X {}; 39 40 struct Y { 41 INJECT(Y(X_ANNOT)) {}; 42 }; 43 44 fruit::Component<fruit::Required<XAnnot>, YAnnot> getComponent() { 45 return fruit::createComponent(); 46 } 47 48 fruit::Component<XAnnot> getXComponent(X* x) { 49 return fruit::createComponent() 50 .bindInstance<XAnnot, X>(*x); 51 } 52 53 int main() { 54 fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent(getComponent); 55 56 X x{}; 57 58 fruit::Injector<XAnnot> injector(normalizedComponent, getXComponent, &x); 59 injector.get<XAnnot>(); 60 } 61 ''' 62 expect_success( 63 COMMON_DEFINITIONS, 64 source, 65 locals()) 66 67 @parameterized.parameters([ 68 ('X', 'X', 'Y'), 69 ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, X)', 'fruit::Annotated<Annotation2, Y>'), 70 ]) 71 def test_success(self, XAnnot, X_ANNOT, YAnnot): 72 source = ''' 73 struct X {}; 74 75 struct Y { 76 INJECT(Y(X_ANNOT)) {}; 77 }; 78 79 fruit::Component<fruit::Required<XAnnot>, YAnnot> getComponent() { 80 return fruit::createComponent(); 81 } 82 83 fruit::Component<XAnnot> getXComponent(X* x) { 84 return fruit::createComponent() 85 .bindInstance<XAnnot, X>(*x); 86 } 87 88 int main() { 89 fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent(getComponent); 90 91 X x{}; 92 93 fruit::Injector<YAnnot> injector(normalizedComponent, getXComponent, &x); 94 injector.get<YAnnot>(); 95 } 96 ''' 97 expect_success( 98 COMMON_DEFINITIONS, 99 source, 100 locals()) 101 102 @parameterized.parameters([ 103 ('X', 'X', 'Y'), 104 ('fruit::Annotated<Annotation1, X>', 'ANNOTATED(Annotation1, X)', 'fruit::Annotated<Annotation2, Y>'), 105 ]) 106 def test_success_inline_component(self, XAnnot, X_ANNOT, YAnnot): 107 source = ''' 108 struct X {}; 109 110 struct Y { 111 INJECT(Y(X_ANNOT)) {}; 112 }; 113 114 fruit::Component<fruit::Required<XAnnot>, YAnnot> getComponent() { 115 return fruit::createComponent(); 116 } 117 118 fruit::Component<XAnnot> getAdditionalComponent(X* x) { 119 return fruit::createComponent() 120 .bindInstance<XAnnot, X>(*x); 121 } 122 123 int main() { 124 fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent(getComponent); 125 126 X x{}; 127 128 fruit::Injector<YAnnot> injector(normalizedComponent, getAdditionalComponent, &x); 129 injector.get<YAnnot>(); 130 } 131 ''' 132 expect_success( 133 COMMON_DEFINITIONS, 134 source, 135 locals()) 136 137 @parameterized.parameters([ 138 'X', 139 'fruit::Annotated<Annotation1, X>', 140 ]) 141 def test_injector_from_normalized_component_unsatisfied_requirements(self, XAnnot): 142 source = ''' 143 struct X {}; 144 145 fruit::Component<fruit::Required<XAnnot>> getComponent(); 146 fruit::Component<> getEmptyComponent(); 147 148 int main() { 149 fruit::NormalizedComponent<fruit::Required<XAnnot>> normalizedComponent(getComponent); 150 fruit::Injector<> injector(normalizedComponent, getEmptyComponent); 151 } 152 ''' 153 expect_compile_error( 154 'UnsatisfiedRequirementsInNormalizedComponentError<XAnnot>', 155 'The requirements in UnsatisfiedRequirements are required by the NormalizedComponent but are not provided by the Component', 156 COMMON_DEFINITIONS, 157 source, 158 locals()) 159 160 @parameterized.parameters([ 161 ('X', 'const X'), 162 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation1, const X>'), 163 ]) 164 def test_normalized_component_providing_nonconst_from_component_providing_const_error(self, XAnnot, ConstXAnnot): 165 source = ''' 166 struct X {}; 167 168 fruit::Component<XAnnot> getComponent(); 169 170 int main() { 171 fruit::NormalizedComponent<ConstXAnnot> normalizedComponent(getComponent); 172 (void) normalizedComponent; 173 } 174 ''' 175 expect_generic_compile_error( 176 r'no matching function for call to .fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent\(fruit::Component<XAnnot> \(&\)\(\)\).' 177 r'|no matching constructor for initialization of .fruit::NormalizedComponent<ConstXAnnot>.' 178 r'|.fruit::NormalizedComponent<ConstXAnnot>::NormalizedComponent.: none of the .* overloads could convert all the argument types', 179 COMMON_DEFINITIONS, 180 source, 181 locals()) 182 183 # TODO: we should probably return a more specific error here. 184 @parameterized.parameters([ 185 ('X', 'Y'), 186 ('fruit::Annotated<Annotation1, X>', 'fruit::Annotated<Annotation2, Y>'), 187 ]) 188 def test_injector_from_normalized_component_nonconst_requirements_provided_as_const_error(self, XAnnot, YAnnot): 189 source = ''' 190 struct X {}; 191 struct Y {}; 192 193 fruit::Component<const XAnnot> getXComponent(); 194 195 void f(fruit::NormalizedComponent<fruit::Required<XAnnot>, YAnnot> normalizedComponent) { 196 fruit::Injector<YAnnot> injector(normalizedComponent, getXComponent); 197 } 198 ''' 199 expect_compile_error( 200 'NonConstBindingRequiredButConstBindingProvidedError<XAnnot>', 201 'The type T was provided as constant, however one of the constructors/providers/factories in this component', 202 COMMON_DEFINITIONS, 203 source, 204 locals()) 205 206if __name__ == '__main__': 207 absltest.main() 208