Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / src / lib / support / tests / TestPersistedStorageImplementation.cpp
1 /*
2  *
3  *    Copyright (c) 2020 Project CHIP Authors
4  *    Copyright (c) 2016-2017 Nest Labs, Inc.
5  *    All rights reserved.
6  *
7  *    Licensed under the Apache License, Version 2.0 (the "License");
8  *    you may not use this file except in compliance with the License.
9  *    You may obtain a copy of the License at
10  *
11  *        http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *    Unless required by applicable law or agreed to in writing, software
14  *    distributed under the License is distributed on an "AS IS" BASIS,
15  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *    See the License for the specific language governing permissions and
17  *    limitations under the License.
18  */
19
20 /**
21  *    @file
22  *      Implementation of a simple std::map based persisted store.
23  *
24  */
25
26 #ifndef __STDC_FORMAT_MACROS
27 #define __STDC_FORMAT_MACROS
28 #endif
29
30 #ifndef __STDC_LIMIT_MACROS
31 #define __STDC_LIMIT_MACROS
32 #endif
33
34 #include <stdint.h>
35 #include <string.h>
36 #include <unistd.h>
37
38 #include <platform/PersistedStorage.h>
39 #include <support/Base64.h>
40 #include <support/CHIPArgParser.hpp>
41 #include <support/CodeUtils.h>
42
43 #include "TestPersistedStorageImplementation.h"
44
45 using namespace chip::ArgParser;
46
47 std::map<std::string, std::string> sPersistentStore;
48
49 FILE * sPersistentStoreFile = nullptr;
50
51 namespace chip {
52 namespace Platform {
53 namespace PersistedStorage {
54
55 static void RemoveEndOfLineSymbol(char * str)
56 {
57     size_t len = strlen(str) - 1;
58     if (str[len] == '\n')
59         str[len] = '\0';
60 }
61
62 static CHIP_ERROR GetCounterValueFromFile(const char * aKey, uint32_t & aValue)
63 {
64     CHIP_ERROR err = CHIP_NO_ERROR;
65     char key[CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH];
66     char value[CHIP_CONFIG_PERSISTED_STORAGE_MAX_VALUE_LENGTH];
67
68     rewind(sPersistentStoreFile);
69
70     while (fgets(key, sizeof(key), sPersistentStoreFile) != nullptr)
71     {
72         RemoveEndOfLineSymbol(key);
73
74         if (strcmp(key, aKey) == 0)
75         {
76             if (fgets(value, sizeof(value), sPersistentStoreFile) == nullptr)
77             {
78                 err = CHIP_ERROR_PERSISTED_STORAGE_FAILED;
79             }
80             else
81             {
82                 RemoveEndOfLineSymbol(value);
83
84                 if (!ParseInt(value, aValue, 0))
85                     err = CHIP_ERROR_PERSISTED_STORAGE_FAILED;
86             }
87
88             ExitNow();
89         }
90     }
91
92     err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
93
94 exit:
95     return err;
96 }
97
98 static CHIP_ERROR SaveCounterValueToFile(const char * aKey, uint32_t aValue)
99 {
100     CHIP_ERROR err = CHIP_NO_ERROR;
101     int res;
102     char key[CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH];
103     char value[CHIP_CONFIG_PERSISTED_STORAGE_MAX_VALUE_LENGTH];
104
105     snprintf(value, sizeof(value), "0x%08X\n", aValue);
106
107     rewind(sPersistentStoreFile);
108
109     // Find the stored counter value location in the file.
110     while (fgets(key, sizeof(key), sPersistentStoreFile) != nullptr)
111     {
112         RemoveEndOfLineSymbol(key);
113
114         // If value is found in the file then override it.
115         if (strcmp(key, aKey) == 0)
116         {
117             res = fputs(value, sPersistentStoreFile);
118             VerifyOrExit(res != EOF, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED);
119
120             ExitNow();
121         }
122     }
123
124     // If value not found in the file then write the counter key and
125     // the counter value to the end of the file.
126     res = fputs(aKey, sPersistentStoreFile);
127     VerifyOrExit(res != EOF, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED);
128
129     res = fputs("\n", sPersistentStoreFile);
130     VerifyOrExit(res != EOF, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED);
131
132     res = fputs(value, sPersistentStoreFile);
133     VerifyOrExit(res != EOF, err = CHIP_ERROR_PERSISTED_STORAGE_FAILED);
134
135 exit:
136     fflush(sPersistentStoreFile);
137     return err;
138 }
139
140 CHIP_ERROR Read(const char * aKey, uint32_t & aValue)
141 {
142     CHIP_ERROR err = CHIP_NO_ERROR;
143     std::map<std::string, std::string>::iterator it;
144
145     VerifyOrExit(aKey != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
146     VerifyOrExit(strlen(aKey) <= CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH, err = CHIP_ERROR_INVALID_STRING_LENGTH);
147
148     if (sPersistentStoreFile)
149     {
150         err = GetCounterValueFromFile(aKey, aValue);
151     }
152     else
153     {
154         it = sPersistentStore.find(aKey);
155         VerifyOrExit(it != sPersistentStore.end(), err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND);
156
157         size_t aValueLength =
158             Base64Decode(it->second.c_str(), static_cast<uint16_t>(it->second.length()), reinterpret_cast<uint8_t *>(&aValue));
159         VerifyOrExit(aValueLength == sizeof(uint32_t), err = CHIP_ERROR_PERSISTED_STORAGE_FAILED);
160     }
161
162 exit:
163     return err;
164 }
165
166 CHIP_ERROR Write(const char * aKey, uint32_t aValue)
167 {
168     CHIP_ERROR err = CHIP_NO_ERROR;
169
170     VerifyOrExit(aKey != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
171     VerifyOrExit(strlen(aKey) <= CHIP_CONFIG_PERSISTED_STORAGE_MAX_KEY_LENGTH, err = CHIP_ERROR_INVALID_STRING_LENGTH);
172
173     if (sPersistentStoreFile)
174     {
175         err = SaveCounterValueToFile(aKey, aValue);
176     }
177     else
178     {
179         char encodedValue[BASE64_ENCODED_LEN(sizeof(uint32_t)) + 1];
180
181         memset(encodedValue, 0, sizeof(encodedValue));
182         Base64Encode(reinterpret_cast<uint8_t *>(&aValue), sizeof(aValue), encodedValue);
183
184         sPersistentStore[aKey] = encodedValue;
185     }
186
187 exit:
188     return err;
189 }
190
191 } // namespace PersistedStorage
192 } // namespace Platform
193 } // namespace chip