# Features tested in end-to-end tests #### INJECT macro * **TODO** Typical use-case * **TODO** With assisted params * **TODO** Check what happens with non-normalized types (all kinds) #### Binding to an instance * Using `bind(x)` or `bind>(x)`. * Check that calling bindInstance with a non-normalized type (e.g. const pointer, nonconst ptr, etc.) causes an error * Abstract class (ok) * Mismatched type arguments * Bind to subclass #### Interface bindings * Check that bind causes an easy-to-understand error * bind> * Check that bind, bind is allowed if Z derives from Y and Y derives from X * bind with X not a base class of Y * Check that the types passed to bind<> are normalized * Check that bind also means bind(Args...)>, std::function(Args...)>> (with and without Args) ##### Binding to a constructor * Explicitly, with a non-signature (not ok) * Implicitly, with a non-signature (not ok) * Implicitly, with a signature "returning" another type (not ok) * Implicitly, with a signature "returning" an annotated type (not ok) * Explicitly, with a signature that doesn't match any of the type's constructors * Implicitly, with a signature that doesn't match any of the type's constructors * **TODO** Using the Inject typedef * **TODO** Using the INJECT macro * **TODO** Also with no params * **TODO** Also for a templated class * **TODO** Also for a templated constructor (only explicitly or using Inject) * **TODO** With all kinds of non-normalized params (esp. with INJECT) * **TODO** With a constructor mistakenly taking an Assisted or Annotated parameter (instead of just using Assisted/Annotated in the Inject typedef) * For an abstract type (not ok), both implicit and explicit * **TODO** Check that a default-constructible type without an Inject typedef can't be auto-injected ##### Binding to a provider * Returning a value * **TODO: ownership check** Returning a pointer (also check that Fruit takes ownership) * Check that lambdas with captures are forbidden * **TODO** Check that non-lambda functors/functions are forbidden * **TODO** Check that objects without operator() are forbidden * Passing a non-signature type * **TODO** Passing a signature type incompatible with the lambda's signature * **TODO** With a lambda mistakenly taking an Assisted or Annotated parameter (instead of just using Assisted/Annotated in the Inject typedef) * **TODO** For an abstract type (ok) * With a provider that returns nullptr (runtime error) #### Factory bindings * Explicit, using `registerFactory()` * Implicitly, with a signature "returning" an annotated type (not ok) * **TODO** Explicit, using `registerFactory()`, but passing a non-signature * Explicit, using `registerFactory()`, but with a lambda that has a different signature compared to the one given explicitly * Implicitly, with a signature that doesn't match any of the type's constructors * Check that lambdas with captures are forbidden in `registerFactory()` * **TODO** Check that non-lambda functors/functions are forbidden in `registerFactory()` * **TODO** Check that objects without operator() are forbidden in `registerFactory()` * Using the INJECT macro * With some assisted params and some injected params * **TODO** With no assisted params but some injected params * With some assisted params but no injected params * **TODO** With no assisted params and no injected params * **TODO** Using the factory in another class' constructor instead of getting it from the injector directly * **TODO** With a lambda mistakenly taking a Assisted/Annotated parameter (instead of just using Assisted/Annotated in the Inject typedef) * Explicit, for an abstract type (ok) * Implicit, for an abstract class (not ok) * Explicit, with a lambda returning a pointer (not supported) * Explicit, with a lambda returning a unique ptr (ok) * **TODO** With assisted params of all kinds of non-normalized types (especially in ASSISTED) * Implicitly, registering a `std::function` instead of a `std::function(...)>` * Explicitly, registering a `std::function` instead of a `std::function(...)>` * Implicitly, generating a binding for std::function when there is a binding for T * Implicitly, generating a binding for std::function()> when there is a binding for T * **TODO** Check that assisted params are passed in the right order when there are multiple * **TODO** Try calling the factory multiple times * Injecting a std::function(...)> with T not movable #### Annotated bindings * **TODO** Using `fruit::Annotated<>` * **TODO** Using the ANNOTATED macro (only in constructors using INJECT) * **TODO** Check possibly-misleading behavior of binding Annotated and Annotated to C (only 1 C instance is created and shared) * **TODO** With assisted params of all kinds of non-normalized types (especially in ANNOTATED) #### Multibindings * Interface multibindings * **TODO** Check that addMultibinding causes an easy-to-understand error * Instance multibindings * **TODO** Check that calling addInstanceMultibinding with a non-normalized type (e.g. const pointer, nonconst ptr, etc.) causes an error * **TODO** `addInstanceMultibindings(x)`, `addInstanceMultibindings(x)` and `addInstanceMultibindings>(x)` * **TODO** `addInstanceMultibindings()` with an empty vector * **TODO** Check that calling `addInstanceMultibindings()` with a non-normalized type causes an error * `addMultibindingProvider`: * Returning a value * **TODO: ownership check** Returning a pointer (also check that Fruit takes ownership) * Check that lambdas with captures are forbidden * **TODO** Check that non-lambda functors/functions are forbidden * **TODO** Check that objects without operator() are forbidden * Passing a non-signature type * **TODO** Passing a signature type incompatible with the lambda's signature * **TODO** With a lambda mistakenly taking an Assisted or Annotated parameter (instead of just using Assisted/Annotated in the Inject typedef) * For an abstract type (not ok) * With a provider that returns nullptr (runtime error) #### PartialComponent and Component * copy a Component * move a Component * move a PartialComponent * construction of a Component from another Component * construction of a Component from a PartialComponent * install() (old and new style) * Type already bound (various combinations, incl. binding+install) * No binding found for abstract class * Dependency loops * Run-time error for multiple inconsistent bindings in different components * Class-level static_asserts in Component * Check that there are no repeated types * Check that no type is both in Required<> and outside * Check that all types are normalized * Check that Required only appears once * Check that Required only appears as first parameter (if at all) #### Normalized components * Constructing an injector from NC + C * **TODO** Constructing an injector from NC + C with empty NC or empty C * With requirements * Class-level static_asserts * Check that there are no repeated types * Check that no type is both in Required<> and outside * **TODO** Check that all types are normalized * Check that Required only appears once * Check that Required only appears as first parameter (if at all) #### Components with requirements * Usual case (where the required type is only forward-declared, with no definition available) * Usual case (where the required type is defined but it's an abstract class) * **TODO** Check that requirements aren't allowed in injectors * Check that multiple Required<...> params are not allowed * Check that the Required<...> param is only allowed if it's the 1st * **TODO** Check that an empty Required<...> param is allowed #### Injectors * **TODO** `std::move()`-ing an injector * Getting instances from an Injector: * **TODO** Using `get` (for all type variations) * **TODO** Using `get()` or casting to try to get a value that the injector doesn't provide * **TODO** Casting the injector to the desired type * Getting multibindings from an Injector * for a type that has no multibindings * for a type that has 1 multibinding * for a type that has >1 multibindings * **TODO** Eager injection * **TODO** Check that the component (in the constructor from C) has no requirements * **TODO** Check that the resulting component (in the constructor from C+NC) has no requirements * **TODO: partial** Empty injector (construct, get multibindings, eager injection, etc.) * **TODO** Injector with a single instance type bound and nothing else * **TODO** Injector with a single bindProvider and nothing else * **TODO** Injector with a single multibinding and nothing else * **TODO** Injector with a single factory and nothing else * Injector where the C doesn't provide T * Injector where the C+NC don't provide T * Class-level static_asserts * Check that there are no repeated types * Check that all types are normalized * Check that there are no Required types #### Injecting Provider<>s * **TODO** In constructors * Getting a Provider<> from an injector using get<> or casting the injector) * **TODO** Getting a Provider<> from an injector by casting the injector * In a constructor and calling get() before the constructor completes * **TODO** casting a Provider to the desired value instead of calling `get()` * **TODO** Calling either `get()` or `get()` on the Provider * **TODO** Check that a Provider's type argument is normalized and not annotated * Copying a Provider and using the copy * Using `get()` to try to get a value that the provider doesn't provide * Class-level static_asserts * Check that the type is normalized * Check that the type is not annotated