Skip to content

Test plan for "default interface implementations" #19217

@gafter

Description

@gafter

This is a test plan for the "default interface implementation" language feature. For reference, see also:

Meta items

  • Let's review all the existing attributes that are allowed on class or struct contexts, but not interface. Maybe they should be updated to allow interface too. For example, SkipLocalsInitAttribute.

Productivity

  • Fixer to remove accessibility in interface I { public void M(); }

Test Functional Changes

  • Test that one can define members of every language-supported protection level
  • Test that access control works as specified for interface members
    • Test that an interface member can call protected member object.MemberwiseClone() on itself
  • Test that private methods are non-virtual by default, other methods are virtual by default
  • Test that abstract is permitted where redundant.
  • Test that abstract is forbidden on private members
  • Test that sealed can be used to make members non-virtual (every access level)
  • Test that there are no implicit implementations in interfaces (you just get a new member)
  • Test that interfaces can be partial [This is not part of the feature, partial interfaces are already supported]
  • Test that partial methods can be written in an interface
  • Test that it is an error to define a private or sealed method without a body in an interface
  • Test that one can declare a constant in an interface, and use it where accessible
  • Test that a class need not implement an interface member with a DIM
  • Test that a class need not implement an interface member with a DIM in a derived interface
  • Test that a class gets an error if it does not implement an interface member with ambiguous DIMs from multiple interfaces (a. ambiguous at class b. ambiguous at implemented interface)
  • Test that one can define a Main method in an interface. [Unit-tests EntryPoint_*]
  • Test that one can define an interface property with a private setter, and implement it implicitly in a class whose property has a setter https://github.com/dotnet/csharplang/blob/master/meetings/2018/LDM-2018-10-17.md#properties-with-a-private-accessor
  • Test that the autoproperty syntax with an initializer is rejected
  • Test that the static autoproperty syntax with an initializer is accepted
  • Test that interface static constructors can be written in an interface, and show when they are run
  • Test calling base(I).M where M is defined and implemented in I.
  • Test calling base(I).M where M is defined in I's base and implemented in I.
  • Test calling base(I).M where M is defined and implemented in I's base (an error)
  • Test calling base(object).M where M is a public/protected member in object.
  • Test base(I).M for virtual method whose implementation is inherited into I (an error)
  • Test runtime behavior for binary compatibility callingbase(I).M for virtual method whose implementation is now inherited into I (a runtime error at the call site)
  • Test taking a delegate to a base(I).M method
  • Test that in binary compatibility scenarios, taking a delegate to an interface method that has no most specific implementation at runtime throws an exception at delegate creation time.
  • Test base(C).M for C a class. (methods and other members). M may not be inherited (even for a constant, field, nonvirtual method) https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-02-27.md#semantics-of-basetmember
  • Test base(I).M for non-virtual method inherited into I (an error)
  • Test that static fields can be defined and used in an interface
  • Test that within an instance method of an interface, this is of the type of the interface and is readonly.
  • Test that the extern modifier is permitted on interface members.
  • Test that abstract or public or sealed may be written in an interface where it is redundant (except...)
  • Test that a private function member may not be declared sealed.
  • Test declaring nested types in an interface.
    • Nested generic types
  • Test that operator declarations (other than conversions and equality) can be declared in an interface and work "as expected".
    • A derived class does not "inherit" the operators, but a derived interface does.
  • Test that conversion operator declarations are forbidden
  • Test whether or not explicit reabstraction works as specified in an interface and class https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md#reabstraction
  • Test that reabstraction works for an implicit override in a class https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md#reabstraction-in-a-class-closed
  • Test (by hand) and document the effect of interfaces with DIM declarations and interface overrides in code as seen by older compilers (C#, VB, F#, C++).
    • Both callers of APIs
    • implementers of interfaces.
    • Use of APIs at other-than-public access
    • Constants, Nested types
  • Test that basic APIs work for code in an interface (tested indirectly by IDE scenarios)
    • SemanticModel methods
      • GetDeclaredSymbol
      • LookupSymbols
      • AnalyzeStatementsControlFlow
      • AnalyzeStatementsDataFlow
    • IOperation
    • ControlFlowGraph
  • Test that DIM methods work in a struct that implements the interface
    • Show that this is boxed by the call
    • Even when invoked through a constrained call
  • Test that unsafe code works
  • Test that async methods work
  • Test that async iterator methods work
  • Test that iterator methods work
  • Test that ref returns work, and have escape scopes checked
  • Test that reference assemblies produce correct output for DIMs and nested types
  • Test that a compiler-generated cache for a delegate is static [LambdaCaching_* in https://github.com/Ensure synthesized BoundBaseReference always uses correct type. #34500]
  • Test that we make a proxy for a delegate of a base call in a lambda [BaseAccessWrapper_01 in https://github.com/Ensure synthesized BoundBaseReference always uses correct type. #34500]
  • Test that field-like events are implicitly abstract (as always)
  • Test that a constructor in an interface is forbidden
  • Test that circular static initialization works at runtime
  • Check that we document that moving implementations is a breaking change
  • Check that the override keyword is forbidden
  • Test that we detect whether the runtime supports the feature before compiling code to new CLR features [There are a lot of tests covering ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember and ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember errors]
  • Test that base(object) works in an interface
  • Test that name lookup from base(I) also finds members of object.
  • Test that using static works as expected when the named type is an interface.

IDE Tests

  • Need IDE merge signoff on core scenarios https://github.com/dotnet/roslyn/wiki/Manual-Testing#core-scenarios-in-editing-navigating-and-viewing
    • Feature enabled/disabled by language version
    • Can type and paste new constructs without interference in verbatim typing
    • Completion of modifiers on interface members
    • dotting and completion off base(Type) [ The following issues are tracked in https://github.com/DefaultInterfaceImplementation open issues and work items #17952: No recommendation/completion for types within base(...) expression. For base access, when the explicit base is an interface, interface members are not suggested, members of the immediate base class are suggested instead. For base access, when the explicit base is a class, members of the immediate base class are suggested regardless of the actual class specified.]
    • Completion in explicit interface member type, name
    • Formatting of code in interfaces
    • Auto-insert close brace in bodies, properties
    • Typing <enter> in an unfinished statement indents the next line
    • control-F12 to navigate from virtual member to implementations
    • Jump from inheritable nested types to their implementations
    • Find all references from interface members of all access
    • Find references from a reference in an implementation
    • Colorization works in interface code
    • Squiggles appear on errors in interface code
  • Test that extract method works
  • Test that completion works to help name/select an explicitly implemented method
  • Test that the IDE offers completion suggestions for access modifiers
  • Test EnC works in function members in an interface
  • Test that debugging works for function members in an interface (stepping, setting breakpoints, displaying locals, watch window, completion in watch window)
  • Test the upgrade project fixer for the feature
  • Test LUT instrumentation

Some ideas from a recent PR for your consideration (you evaluate the risk and decide if it's worthwhile to cover):

  • interface containing a type containing a nested type
  • interface containing a generic type (with its own T, or with T from the containing interface)
  • interface containing two chunks of a partial type
  • interface containing a partial method and also the partial method implementation
  • interface containing a static type
  • interface containing a type containing an interface containing a type
  • LINQ query on interface (select x from IMyIEnumerableWithSelect, select object x from IMyIEnumerableWithCast)

Consider benchmarking the feature.

Also, we may need to update some analyzer and our public API compat tracker. It's probably good to notify CoreFX team to do the same.

Metadata

Metadata

Assignees

Labels

Area-CompilersFeature - Default Interface ImplDefault Interface ImplementationTestTest failures in roslyn-CITest-GapDescribes a specific feature or scenario that does not have test coverage

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions