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
16 #include "c_mock.h"
17
18 #include <dlfcn.h>
19
20 namespace OHOS::FileManagement::ModuleFileIO::Test {
21
22 thread_local std::shared_ptr<CMock> CMock::cMock = nullptr;
23 thread_local bool CMock::mockable = false;
24
GetMock()25 std::shared_ptr<CMock> CMock::GetMock()
26 {
27 if (cMock == nullptr) {
28 cMock = std::make_shared<CMock>();
29 }
30 return cMock;
31 }
32
EnableMock()33 void CMock::EnableMock()
34 {
35 mockable = true;
36 }
37
DisableMock()38 void CMock::DisableMock()
39 {
40 cMock = nullptr;
41 mockable = false;
42 }
43
IsMockable()44 bool CMock::IsMockable()
45 {
46 return mockable;
47 }
48
49 } // namespace OHOS::FileManagement::ModuleFileIO::Test
50
51 #ifdef __cplusplus
52 extern "C" {
53 using namespace OHOS::FileManagement::ModuleFileIO::Test;
54
fseek(FILE * stream,long len,int offset)55 int fseek(FILE *stream, long len, int offset)
56 {
57 if (CMock::IsMockable()) {
58 return CMock::GetMock()->fseek(stream, len, offset);
59 }
60
61 static int (*realFseek)(FILE *, long, int) = []() {
62 auto func = (int (*)(FILE *, long, int))dlsym(RTLD_NEXT, "fseek");
63 if (!func) {
64 GTEST_LOG_(ERROR) << "Failed to resolve real fseek: " << dlerror();
65 }
66 return func;
67 }();
68
69 if (!realFseek) {
70 return -1;
71 }
72
73 return realFseek(stream, len, offset);
74 }
75
ftell(FILE * stream)76 long ftell(FILE *stream)
77 {
78 if (CMock::IsMockable()) {
79 return CMock::GetMock()->ftell(stream);
80 }
81
82 static long (*realFtell)(FILE *) = []() {
83 auto func = (long (*)(FILE *))dlsym(RTLD_NEXT, "ftell");
84 if (!func) {
85 GTEST_LOG_(ERROR) << "Failed to resolve real ftell: " << dlerror();
86 }
87 return func;
88 }();
89
90 if (!realFtell) {
91 return -1;
92 }
93
94 return realFtell(stream);
95 }
96 } // extern "C"
97 #endif