• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *	http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "functionalext.h"
16 #include <cstdio>
17 #include <cstdlib>
18 
19 #include "a.h"
20 #include "b.h"
21 
22 struct Last {};
23 
24 template <typename FirstT, typename... NextT>
25 struct Types {
26     using First = FirstT;
27     using Next = Types<NextT...>;
28 };
29 
30 template <typename FirstT>
31 struct Types<FirstT> {
32     using First = FirstT;
33     using Next = Last;
34 };
35 
CtorDtorTests_TestClassA()36 static void CtorDtorTests_TestClassA() {
37     int initA = 1;
38     liba::Class *a = new liba::Class(initA);
39     const char *payloadA = "Class A payload\n";
40     int retA = a->Payload(payloadA);
41     delete a;
42     EXPECT_EQ(__func__, retA, initA + 2);
43 }
44 
CtorDtorTests_TestClassB()45 static void CtorDtorTests_TestClassB() {
46     int initB = 2;
47     libb::Class *b = new libb::Class(initB);
48     const char *payloadB = "Class B payload\n";
49     int retB = b->Payload(payloadB);
50     delete b;
51     EXPECT_EQ(__func__, retB, initB + 2);
52 }
53 
54 template <typename T, int Add = 0> struct InitA {
55     using Type = T;
56     static constexpr int InitVal = 1;
57     static constexpr int AddVal = Add;
58 };
59 
60 template <typename T, int Add = 0> struct InitB {
61     using Type = T;
62     static constexpr int InitVal = 2;
63     static constexpr int AddVal = Add;
64 };
65 
66 using PolyTypes =
67         Types<InitA<liba::GlobalPoly, 0>, InitB<libb::GlobalPoly, 0>,
68                                          InitA<liba::InlinePoly, 10>, InitB<libb::InlinePoly, 10>,
69                                          InitA<liba::LocalPoly, 20>, InitB<libb::LocalPoly, 20>>;
70 
71 template <typename PolyT> class VtableTests {
72 public:
TestVirtualMethod()73     void TestVirtualMethod() {
74         int initVal = PolyT::InitVal;
75         auto *ptr = PolyT::Type::New(initVal);
76         EXPECT_EQ(__func__, ptr->VirtualMethod(), initVal);
77         delete ptr;
78     }
79 
TestDerivedVirtualMethod()80     void TestDerivedVirtualMethod() {
81         int initVal = PolyT::InitVal;
82         int addVal = PolyT::AddVal;
83         auto *ptr = PolyT::Type::NewDerived(initVal);
84         EXPECT_EQ(__func__, ptr->VirtualMethod(), initVal + 10 + addVal);
85         delete ptr;
86     }
87 };
88 
TestVtable_GlobalPoly()89 static void TestVtable_GlobalPoly() {
90     VtableTests<InitA<liba::GlobalPoly, 0>> tests;
91     tests.TestVirtualMethod();
92     tests.TestDerivedVirtualMethod();
93 }
94 
TestVtable_LocalPoly()95 static void TestVtable_LocalPoly() {
96     VtableTests<InitA<liba::LocalPoly, 20>> tests;
97     tests.TestVirtualMethod();
98     tests.TestDerivedVirtualMethod();
99 }
100 
101 using DiamondTypes =
102         Types<InitA<liba::DiamondChild>, InitB<libb::DiamondChild>>;
103 
104 template <typename DiamondT>
105 class VirtualInheritanceTests {
106 public:
createRoot(int val)107     __attribute__((noinline)) liba::DiamondRoot *createRoot(int val) {
108         return new liba::DiamondRoot(val);
109     }
createLeft(int val,int leftVal)110     __attribute__((noinline)) liba::DiamondRoot *createLeft(int val, int leftVal) {
111         return new liba::DiamondLeft(val, leftVal);
112     }
createRight(int val,int rightVal)113     __attribute__((noinline)) liba::DiamondRoot *createRight(int val, int rightVal) {
114         return new liba::DiamondRight(val, rightVal);
115     }
116     __attribute__((noinline)) liba::DiamondRoot *
createChild(int val,int leftVal,int rightVal,int childVal)117     createChild(int val, int leftVal, int rightVal, int childVal) {
118         return new liba::DiamondChild(val, leftVal, rightVal, childVal);
119     }
120 
TestRoot()121     void TestRoot() {
122         int initVal = DiamondT::InitVal;
123         auto *ptr = createRoot(initVal);
124         EXPECT_EQ(__func__, ptr->VirtualMethod(), initVal);
125         EXPECT_EQ(__func__, ptr->VirtualMethod1(), initVal + 1);
126         EXPECT_EQ(__func__, ptr->VirtualMethod2(), initVal - 1);
127         EXPECT_EQ(__func__, ptr->VirtualMethod3(), initVal * 2);
128         delete ptr;
129     }
130 
TestLeft()131     void TestLeft() {
132         int initVal = DiamondT::InitVal;
133         int leftVal = 10 + initVal;
134         auto *ptr = createLeft(initVal, leftVal);
135         EXPECT_EQ(__func__, ptr->VirtualMethod(), initVal);
136         EXPECT_EQ(__func__, ptr->VirtualMethod1(), leftVal);
137         EXPECT_EQ(__func__, ptr->VirtualMethod2(), initVal - 1);
138         EXPECT_EQ(__func__, ptr->VirtualMethod3(), initVal * 2);
139         delete ptr;
140     }
141 
TestRight()142     void TestRight() {
143         int initVal = DiamondT::InitVal;
144         int rightVal = 20 + initVal;
145         auto *ptr = createRight(initVal, rightVal);
146         EXPECT_EQ(__func__, ptr->VirtualMethod(), initVal);
147         EXPECT_EQ(__func__, ptr->VirtualMethod1(), initVal + 1);
148         EXPECT_EQ(__func__, ptr->VirtualMethod2(), rightVal);
149         EXPECT_EQ(__func__, ptr->VirtualMethod3(), initVal * 2);
150         delete ptr;
151     }
152 
TestChild()153     void TestChild() {
154         int initVal = DiamondT::InitVal;
155         int leftVal = 10 + initVal;
156         int rightVal = 20 + initVal;
157         int childVal = 30 + initVal;
158         auto *ptr = createChild(initVal, leftVal, rightVal, childVal);
159         EXPECT_EQ(__func__, ptr->VirtualMethod(), initVal);
160         EXPECT_EQ(__func__, ptr->VirtualMethod1(), leftVal);
161         EXPECT_EQ(__func__, ptr->VirtualMethod2(), rightVal);
162         EXPECT_EQ(__func__, ptr->VirtualMethod3(), childVal);
163         delete ptr;
164     }
165 };
166 
TestDiamondChild()167 static void TestDiamondChild() {
168     VirtualInheritanceTests<InitA<liba::DiamondChild>> tests;
169     tests.TestRoot();
170     tests.TestLeft();
171     tests.TestRight();
172     tests.TestChild();
173 }
174 
main(int argc,char ** argv)175 int main(int argc, char **argv) {
176     CtorDtorTests_TestClassA();
177     CtorDtorTests_TestClassB();
178     TestVtable_GlobalPoly();
179     TestVtable_LocalPoly();
180     TestDiamondChild();
181     return t_status;
182 }