blob: cde64b07cb25c150baeefa30ed9b8edf23b784c2 [file]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:test/test.dart';
import 'cpp_inheritance_test_bindings.dart';
void main() {
group('C++ Inheritance', () {
test('Single inheritance - Circle implements Shape', () {
final circle = Circle(10.0, 20.0, 5.0);
// Polymorphic interface conformance in Dart
expect(circle, isA<Shape>());
// Own methods
expect(circle.area(), closeTo(78.5398, 0.001));
// Inherited methods from Shape
expect(circle.getX(), 10.0);
expect(circle.getY(), 20.0);
circle.dispose();
});
test('Multiple inheritance - ColoredCircle', () {
final coloredCircle = ColoredCircle(1.0, 2.0, 3.0, 0xFF00FF);
// Polymorphic interface conformance
expect(coloredCircle, isA<Circle>());
expect(coloredCircle, isA<Shape>());
expect(coloredCircle, isA<Drawable>());
// Own method
expect(coloredCircle.getColor(), 0xFF00FF);
// Inherited from Circle
expect(coloredCircle.area(), closeTo(28.2743, 0.001));
// Inherited from Shape (transitive)
expect(coloredCircle.getX(), 1.0);
expect(coloredCircle.getY(), 2.0);
// Inherited from Drawable (multiple inheritance branch)
expect(coloredCircle.draw(), 42);
coloredCircle.dispose();
});
test('Virtual method override - Square overrides getX', () {
final square = Square(5.0, 10.0, 4.0);
expect(square, isA<Shape>());
expect(square.area(), 16.0);
expect(square.getY(), 10.0);
// Overridden getX() returns x + side = 5.0 + 4.0 = 9.0
expect(square.getX(), 9.0);
square.dispose();
});
test('Polymorphic delegation via interface types', () {
final shapes = <Shape>[Circle(0.0, 0.0, 1.0), Square(10.0, 20.0, 5.0)];
expect(shapes[0].getX(), 0.0);
expect(shapes[1].getX(), 15.0); // 10 + 5 via virtual override
for (final shape in shapes) {
shape.dispose();
}
});
test('Access specifier filtering - Public vs Private/Protected base', () {
// PublicDerived inherits public AccessBase -> implements AccessBase
final publicDerived = PublicDerived();
expect(publicDerived, isA<AccessBase>());
expect(publicDerived.value(), 99);
publicDerived.dispose();
// ProtectedDerived and PrivateDerived do NOT implement AccessBase
final protectedDerived = ProtectedDerived();
expect(protectedDerived, isNot(isA<AccessBase>()));
protectedDerived.dispose();
final privateDerived = PrivateDerived();
expect(privateDerived, isNot(isA<AccessBase>()));
privateDerived.dispose();
});
test('Throw StateError on inherited methods after dispose', () {
final circle = Circle(1.0, 2.0, 3.0);
circle.dispose();
expect(circle.getX, throwsStateError);
expect(circle.getY, throwsStateError);
expect(circle.area, throwsStateError);
});
test('Overload handling - OverloadDerived overrides & inherits', () {
final overload = OverloadDerived();
expect(overload, isA<OverloadBase>());
// Overridden getValue(int): 5 * 10 = 50
expect(overload.getValue(5), 50);
// Inherited getValueDouble(double): 5.0 * 3.0 = 15.0
expect(overload.getValueDouble(5.0), closeTo(15.0, 0.001));
overload.dispose();
});
test('Diamond inheritance - DiamondDerived inherits from both sides', () {
final d = DiamondDerived();
// DiamondDerived implements both DiamondLeft and DiamondRight
expect(d, isA<DiamondLeft>());
expect(d, isA<DiamondRight>());
// And transitively implements DiamondBase through each branch
expect(d, isA<DiamondBase>());
// baseVal() is delegated through DiamondLeft (first direct base),
// which itself dispatches through C++ — no ambiguity.
expect(d.baseVal(), 42);
// virtVal() is overridden by DiamondLeft to return 200
expect(d.virtVal(), 200);
d.dispose();
});
});
}