Skip to content

Commit 3d09133

Browse files
amabluea-maurice
authored andcommitted
Minor cleanup: removed the database's SafeRef, since the repo already has one, and the repo can wrap things in a safe ref lock itself. Having two ways to lock things is redundant when everything is being routed through Repo anyway.
PiperOrigin-RevId: 256103848
1 parent 021d99b commit 3d09133

37 files changed

+1495
-58
lines changed

app/rest/transport_mock.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "app/rest/transport_mock.h"
1818
#include <string>
1919
#include "app/rest/util.h"
20-
#include "firebase/testing/cppsdk/config_desktop.h"
20+
#include "testing/config_desktop.h"
2121

2222
namespace firebase {
2323
namespace rest {

database/src/desktop/core/repo.cc

Lines changed: 35 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -296,25 +296,25 @@ void Repo::PurgeOutstandingWrites() {
296296
// triggered.
297297
class SetValueResponse : public connection::Response {
298298
public:
299-
SetValueResponse(const DatabaseInternal::ThisRef& database, const Path& path,
299+
SetValueResponse(const Repo::ThisRef& repo, const Path& path,
300300
WriteId write_id, ReferenceCountedFutureImpl* api,
301301
SafeFutureHandle<void> handle, ResponseCallback callback)
302302
: connection::Response(callback),
303-
database_ref_(database),
303+
repo_ref_(repo),
304304
path_(path),
305305
write_id_(write_id),
306306
api_(api),
307307
handle_(handle) {}
308308

309-
DatabaseInternal::ThisRef& database_ref() { return database_ref_; }
309+
Repo::ThisRef& repo_ref() { return repo_ref_; }
310310
const Path& path() { return path_; }
311311
WriteId write_id() { return write_id_; }
312312
ReferenceCountedFutureImpl* api() { return api_; }
313313
SafeFutureHandle<void> handle() { return handle_; }
314314

315315
private:
316-
// Database reference
317-
DatabaseInternal::ThisRef database_ref_;
316+
// Repo reference
317+
Repo::ThisRef repo_ref_;
318318

319319
// Database path for this write request
320320
Path path_;
@@ -339,22 +339,21 @@ void Repo::SetValue(const Path& path, const Variant& new_data_unresolved,
339339
kPersist);
340340
PostEvents(events);
341341

342-
connection_->Put(
343-
path, new_data_unresolved,
344-
MakeShared<SetValueResponse>(
345-
DatabaseInternal::ThisRef(database_), path, write_id, api, handle,
346-
[](const connection::ResponsePtr& ptr) {
347-
auto* response = static_cast<SetValueResponse*>(ptr.get());
348-
DatabaseInternal::ThisRefLock lock(&response->database_ref());
349-
DatabaseInternal* database = lock.GetReference();
350-
Repo* repo = database->repo();
351-
repo->AckWriteAndRerunTransactions(response->write_id(),
352-
response->path(),
353-
response->GetErrorCode());
354-
response->api()->Complete(
355-
response->handle(), response->GetErrorCode(),
356-
GetErrorMessage(response->GetErrorCode()));
357-
}));
342+
connection_->Put(path, new_data_unresolved,
343+
MakeShared<SetValueResponse>(
344+
Repo::ThisRef(this), path, write_id, api, handle,
345+
[](const connection::ResponsePtr& ptr) {
346+
auto* response =
347+
static_cast<SetValueResponse*>(ptr.get());
348+
Repo::ThisRefLock lock(&response->repo_ref());
349+
Repo* repo = lock.GetReference();
350+
repo->AckWriteAndRerunTransactions(
351+
response->write_id(), response->path(),
352+
response->GetErrorCode());
353+
response->api()->Complete(
354+
response->handle(), response->GetErrorCode(),
355+
GetErrorMessage(response->GetErrorCode()));
356+
}));
358357

359358
Path affected_path = AbortTransactions(path, kErrorOverriddenBySet);
360359
RerunTransactions(affected_path);
@@ -379,22 +378,21 @@ void Repo::UpdateChildren(const Path& path, const Variant& data,
379378
path, updates, resolved, write_id, kPersist);
380379
PostEvents(events);
381380

382-
connection_->Merge(
383-
path, data,
384-
MakeShared<SetValueResponse>(
385-
DatabaseInternal::ThisRef(database_), path, write_id, api, handle,
386-
[](const connection::ResponsePtr& ptr) {
387-
auto* response = static_cast<SetValueResponse*>(ptr.get());
388-
DatabaseInternal::ThisRefLock lock(&response->database_ref());
389-
DatabaseInternal* database = lock.GetReference();
390-
Repo* repo = database->repo();
391-
repo->AckWriteAndRerunTransactions(response->write_id(),
392-
response->path(),
393-
response->GetErrorCode());
394-
response->api()->Complete(
395-
response->handle(), response->GetErrorCode(),
396-
GetErrorMessage(response->GetErrorCode()));
397-
}));
381+
connection_->Merge(path, data,
382+
MakeShared<SetValueResponse>(
383+
Repo::ThisRef(this), path, write_id, api, handle,
384+
[](const connection::ResponsePtr& ptr) {
385+
auto* response =
386+
static_cast<SetValueResponse*>(ptr.get());
387+
Repo::ThisRefLock lock(&response->repo_ref());
388+
Repo* repo = lock.GetReference();
389+
repo->AckWriteAndRerunTransactions(
390+
response->write_id(), response->path(),
391+
response->GetErrorCode());
392+
response->api()->Complete(
393+
response->handle(), response->GetErrorCode(),
394+
GetErrorMessage(response->GetErrorCode()));
395+
}));
398396

399397
updates.write_tree().CallOnEach(
400398
Path(), [this](const Path& path_from_root, const Variant& variant) {

database/src/desktop/database_desktop.cc

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include <queue>
1818
#include <stack>
19+
1920
#include "app/memory/shared_ptr.h"
2021
#include "app/src/assert.h"
2122
#include "app/src/function_registry.h"
@@ -67,7 +68,6 @@ DatabaseInternal::DatabaseInternal(App* app, const char* url)
6768
: app_(app),
6869
future_manager_(),
6970
cleanup_(),
70-
safe_this_(this),
7171
constructor_url_(url),
7272
repo_(app, this, url),
7373
log_level_(kLogLevelInfo) {
@@ -81,9 +81,6 @@ DatabaseInternal::DatabaseInternal(App* app, const char* url)
8181

8282
DatabaseInternal::~DatabaseInternal() {
8383
cleanup_.CleanupAll();
84-
// Clear safe reference immediately so that scheduled callback can skip
85-
// executing code which requires reference to this.
86-
safe_this_.ClearReference();
8784

8885
// If initialization failed, there is nothing to clean up.
8986
if (app_ == nullptr) return;
@@ -142,35 +139,35 @@ DatabaseReference DatabaseInternal::GetReferenceFromUrl(const char* url) const {
142139

143140
void DatabaseInternal::GoOffline() {
144141
Repo::scheduler().Schedule(NewCallback(
145-
[](ThisRef ref) {
146-
ThisRefLock lock(&ref);
142+
[](Repo::ThisRef ref) {
143+
Repo::ThisRefLock lock(&ref);
147144
if (lock.GetReference() != nullptr) {
148-
lock.GetReference()->repo_.connection()->Interrupt();
145+
lock.GetReference()->connection()->Interrupt();
149146
}
150147
},
151-
safe_this_));
148+
repo_.this_ref()));
152149
}
153150

154151
void DatabaseInternal::GoOnline() {
155152
Repo::scheduler().Schedule(NewCallback(
156-
[](ThisRef ref) {
157-
ThisRefLock lock(&ref);
153+
[](Repo::ThisRef ref) {
154+
Repo::ThisRefLock lock(&ref);
158155
if (lock.GetReference() != nullptr) {
159-
lock.GetReference()->repo_.connection()->Resume();
156+
lock.GetReference()->connection()->Resume();
160157
}
161158
},
162-
safe_this_));
159+
repo_.this_ref()));
163160
}
164161

165162
void DatabaseInternal::PurgeOutstandingWrites() {
166163
Repo::scheduler().Schedule(NewCallback(
167-
[](ThisRef ref) {
168-
ThisRefLock lock(&ref);
164+
[](Repo::ThisRef ref) {
165+
Repo::ThisRefLock lock(&ref);
169166
if (lock.GetReference() != nullptr) {
170-
lock.GetReference()->repo_.PurgeOutstandingWrites();
167+
lock.GetReference()->PurgeOutstandingWrites();
171168
}
172169
},
173-
safe_this_));
170+
repo_.this_ref()));
174171
}
175172

176173
static std::string* g_sdk_version = nullptr;

database/src/desktop/database_desktop.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,10 +185,6 @@ class DatabaseInternal {
185185
// Needed to generate names that are guarenteed to be unique.
186186
PushChildNameGenerator name_generator_;
187187

188-
// Safe reference to this. Set in constructor and cleared in destructor
189-
// Should be safe to be copied to any thread.
190-
ThisRef safe_this_;
191-
192188
// The url passed to the constructor (or "" if none was passed).
193189
// We keep it so that we can find the database in our cache.
194190
std::string constructor_url_;

testing/TickerExample.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package com.google.firebase.testing.cppsdk;
2+
3+
/** An example subclass of {@link TickerObserver} for unit-testing the ticker mechanism. */
4+
public final class TickerExample implements TickerObserver {
5+
// When the callback should happen.
6+
private final long delay;
7+
8+
public TickerExample(long delay) {
9+
this.delay = delay;
10+
TickerAndroid.register(this);
11+
}
12+
13+
@Override
14+
public void elapse() {
15+
// We pass in ticker directly to save a few JNI calls. A fake should implement the logic right
16+
// here without using native function. We use native function here in order to consolidate logic
17+
// in the unit test .cc file.
18+
nativeFunction(TickerAndroid.now(), delay);
19+
}
20+
21+
private native void nativeFunction(long ticker, long delay);
22+
}

testing/config.cc

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#include "testing/config.h"
2+
3+
#include "base/logging.h"
4+
#include "testing/testdata_config_resource.h"
5+
#include "flatbuffers/idl.h"
6+
7+
namespace firebase {
8+
namespace testing {
9+
namespace cppsdk {
10+
11+
const char* kSchemaFilePath = "";
12+
13+
// Replace the current test data.
14+
void ConfigSet(const char* test_data_in_json) {
15+
flatbuffers::Parser parser;
16+
const char* schema_str =
17+
reinterpret_cast<const char*>(testdata_config_resource_data);
18+
CHECK(parser.Parse(schema_str)) << "Failed to parse schema:" << parser.error_;
19+
CHECK(parser.Parse(test_data_in_json)) << "Invalid JSON:" << parser.error_;
20+
21+
// Assign
22+
internal::ConfigSetImpl(parser.builder_.GetBufferPointer(),
23+
parser.builder_.GetSize());
24+
}
25+
26+
void ConfigReset() { internal::ConfigSetImpl(nullptr, 0); }
27+
28+
} // namespace cppsdk
29+
} // namespace testing
30+
} // namespace firebase

testing/config.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Provide a way for C++ unit test to send test data to fakes. The fakes will
2+
// behave as specified in order to mimic different real world scenarios. See
3+
// goto/firebasecppunittest for more details.
4+
#ifndef FIREBASE_TESTING_CPPSDK_CONFIG_H_
5+
#define FIREBASE_TESTING_CPPSDK_CONFIG_H_
6+
7+
#include <cstdint>
8+
#include "testing/testdata_config_generated.h"
9+
10+
namespace firebase {
11+
namespace testing {
12+
namespace cppsdk {
13+
14+
// Replace the current test data.
15+
void ConfigSet(const char* test_data_in_json);
16+
17+
// Reset (free up) the current test data.
18+
void ConfigReset();
19+
20+
namespace internal {
21+
// Platform-specific function to send the test data.
22+
void ConfigSetImpl(const uint8_t* test_data_binary,
23+
flatbuffers::uoffset_t size);
24+
} // namespace internal
25+
26+
} // namespace cppsdk
27+
} // namespace testing
28+
} // namespace firebase
29+
30+
#endif // FIREBASE_TESTING_CPPSDK_CONFIG_H_

testing/config_android.cc

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include <jni.h>
2+
3+
#include "base/logging.h"
4+
#include "testing/config.h"
5+
#include "testing/run_all_tests.h"
6+
#include "testing/testdata_config_generated.h"
7+
#include "testing/util_android.h"
8+
9+
namespace firebase {
10+
namespace testing {
11+
namespace cppsdk {
12+
namespace internal {
13+
void ConfigSetImpl(const uint8_t* test_data_binary,
14+
flatbuffers::uoffset_t size) {
15+
JNIEnv* android_jni_env = GetTestJniEnv();
16+
jbyteArray j_test_data = nullptr;
17+
if (test_data_binary != nullptr && size > 0) {
18+
j_test_data = android_jni_env->NewByteArray(size);
19+
android_jni_env->SetByteArrayRegion(
20+
j_test_data, 0, size,
21+
reinterpret_cast<jbyte*>(const_cast<uint8_t*>(test_data_binary)));
22+
}
23+
jclass cls = android_jni_env->FindClass(
24+
"com/google/testing/ConfigAndroid");
25+
android_jni_env->CallStaticVoidMethod(
26+
cls, android_jni_env->GetStaticMethodID(cls, "setImpl", "([B)V"),
27+
j_test_data);
28+
util::CheckAndClearException(android_jni_env);
29+
android_jni_env->DeleteLocalRef(j_test_data);
30+
android_jni_env->DeleteLocalRef(cls);
31+
}
32+
} // namespace internal
33+
} // namespace cppsdk
34+
} // namespace testing
35+
} // namespace firebase

testing/config_desktop.cc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include "testing/config_desktop.h"
2+
#include "testing/config.h"
3+
4+
#include <cstdint>
5+
6+
#include "base/logging.h"
7+
#include "app/src/mutex.h"
8+
#include "testing/testdata_config_generated.h"
9+
#include "flatbuffers/idl.h"
10+
11+
namespace firebase {
12+
namespace testing {
13+
namespace cppsdk {
14+
15+
// We keep this raw data in order to be able to return it back for merge.
16+
static uint8_t* g_test_data_config = nullptr;
17+
// Mutex to make sure we don't delete the pointer while someone else is reading.
18+
static Mutex testing_mutex; // NOLINT
19+
// List of all the test data we've used so far, so we can clean it up later.
20+
// (we can't delete it when it's replaced because old threads might still
21+
// be looking at it.)
22+
static std::vector<uint8_t*> g_all_test_data; // NOLINT
23+
24+
const ConfigRow* ConfigGet(const char* fake) {
25+
MutexLock lock(testing_mutex);
26+
CHECK(g_test_data_config != nullptr) << "No test data at all";
27+
const TestDataConfig* config = GetTestDataConfig(g_test_data_config);
28+
// LookupByKey() does not work because the data passed in may not conform. So
29+
// we just iterate over the test data.
30+
for (const ConfigRow* row : *(config->config())) {
31+
if (strcmp(row->fake()->c_str(), fake) == 0) {
32+
return row;
33+
}
34+
}
35+
return nullptr;
36+
}
37+
38+
namespace internal {
39+
void ConfigSetImpl(const uint8_t* test_data_binary,
40+
flatbuffers::uoffset_t size) {
41+
MutexLock lock(testing_mutex);
42+
if (test_data_binary != nullptr && size > 0) {
43+
g_test_data_config = new uint8_t[size];
44+
memcpy(g_test_data_config, test_data_binary, size);
45+
g_all_test_data.push_back(g_test_data_config);
46+
} else {
47+
g_test_data_config = nullptr;
48+
for (int i = 0; i < g_all_test_data.size(); i++) {
49+
delete[] g_all_test_data[i];
50+
}
51+
g_all_test_data.clear();
52+
}
53+
}
54+
} // namespace internal
55+
56+
} // namespace cppsdk
57+
} // namespace testing
58+
} // namespace firebase

testing/config_desktop.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef FIREBASE_TESTING_CPPSDK_CONFIG_DESKTOP_H_
2+
#define FIREBASE_TESTING_CPPSDK_CONFIG_DESKTOP_H_
3+
4+
#include "testing/testdata_config_generated.h"
5+
6+
namespace firebase {
7+
namespace testing {
8+
namespace cppsdk {
9+
10+
// Returns the test data for the specific fake.
11+
const ConfigRow* ConfigGet(const char* fake);
12+
13+
} // namespace cppsdk
14+
} // namespace testing
15+
} // namespace firebase
16+
17+
#endif // FIREBASE_TESTING_CPPSDK_CONFIG_DESKTOP_H_

0 commit comments

Comments
 (0)