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