Skip to content

Commit

Permalink
feat: 增加单测 (#161)
Browse files Browse the repository at this point in the history
* feat: 增加单测

* remove overdue event when database init

Co-authored-by: shenliming <348515494@qq.com>
  • Loading branch information
styluo and cpacm authored Jul 7, 2022
1 parent 2508fc8 commit 99d5222
Show file tree
Hide file tree
Showing 8 changed files with 202 additions and 7 deletions.
3 changes: 2 additions & 1 deletion growingio-adapter/analytics-ga/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/build
/build
jacoco.exec
7 changes: 7 additions & 0 deletions growingio-adapter/analytics-ga/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ android {
testOptions {
unitTests.all {
jacoco {
jvmArgs '-noverify'
includeNoLocationClasses = true
excludes = ['jdk.internal.*']
}
Expand All @@ -43,6 +44,12 @@ dependencies {
testImplementation libraries.test.truth
testImplementation libraries.test.androidx_core
testImplementation libraries.test.robolectric
testImplementation libraries.test.powermock_core
testImplementation libraries.test.powermock_api_mockito2
testImplementation libraries.test.powermock_module_junit4
testImplementation libraries.test.powermock_module_junit4_rule
testImplementation libraries.test.powermock_classloading_xstream
testImplementation "com.google.android.gms:play-services-analytics:18.0.1"

implementation project(':growingio-tracker-core')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,9 @@ public void run() {

// 解析 GA3 配置xml
void newTracker(Tracker tracker, int resId) {
XmlResourceParser parser = null;
try {
XmlResourceParser parser = TrackerContext.get().getResources().getXml(resId);
parser = TrackerContext.get().getResources().getXml(resId);
boolean foundTag = false;
while (parser.getEventType() != XmlResourceParser.END_DOCUMENT) {
if (parser.getEventType() == XmlResourceParser.START_TAG) {
Expand All @@ -139,6 +140,10 @@ void newTracker(Tracker tracker, int resId) {
parser.next();
}
} catch (Exception ignored) {
} finally {
if (parser != null) {
parser.close();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* Copyright (C) 2020 Beijing Yishu Technology Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.growingio.android.analytics.google;

import android.app.Application;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;

import androidx.test.core.app.ApplicationProvider;

import com.google.android.gms.analytics.Tracker;
import com.google.common.truth.Truth;
import com.growingio.android.analytics.google.model.AnalyticsEvent;
import com.growingio.android.sdk.Configurable;
import com.growingio.android.sdk.CoreConfiguration;
import com.growingio.android.sdk.TrackerContext;
import com.growingio.android.sdk.track.events.TrackEventType;
import com.growingio.android.sdk.track.providers.ConfigurationProvider;

import org.json.JSONObject;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
import org.powermock.modules.junit4.rule.PowerMockRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;

import java.io.InputStream;
import java.util.HashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import static org.powermock.api.mockito.PowerMockito.doAnswer;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.when;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.any;

@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 30)
@PowerMockIgnore({
"org.mockito.*",
"org.robolectric.*",
"androidx.*",
"android.*",
"org.json.*"
})
@PrepareOnlyThisForTest({GoogleAnalyticsAdapter.class})
public class GoogleAnalyticsAdapterTest {
GoogleAnalyticsAdapter spyAdapter;
Application spyApplication;
InputStream inputStream;

@Rule
public PowerMockRule powerMockRule = new PowerMockRule();

@Before
public void setup() throws Exception {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
inputStream = getClass().getClassLoader().getResourceAsStream("res/xml/global_tracker.xml");
xpp.setInput(inputStream, "UTF-8");

XmlResourceParser xmlResourceParser = mock(XmlResourceParser.class);
when(xmlResourceParser.getName()).thenAnswer(invocation -> xpp.getName());
when(xmlResourceParser.getAttributeValue(any(), any())).thenAnswer(invocation -> xpp.getAttributeValue(null, "name"));
when(xmlResourceParser.getEventType()).thenAnswer(invocation -> xpp.getEventType());
when(xmlResourceParser.next()).thenAnswer(invocation -> xpp.next());
when(xmlResourceParser.getText()).thenAnswer(invocation -> xpp.getText());
doAnswer(invocation -> {
inputStream.close();
inputStream = getClass().getClassLoader().getResourceAsStream("res/xml/global_tracker.xml");
xpp.setInput(inputStream, "UTF-8");
return null;
}).when(xmlResourceParser).close();

Resources mockResources = mock(Resources.class);
when(mockResources.getXml(anyInt())).thenReturn(xmlResourceParser);

spyApplication = spy(ApplicationProvider.getApplicationContext());
when(spyApplication.getResources()).thenReturn(mockResources);

TrackerContext.init(spyApplication);
TrackerContext.initSuccess();
HashMap<String, String> dataSourceIds = new HashMap<>();
dataSourceIds.put("UA-000000000-1", "0000000000000001");
dataSourceIds.put("UA-000000000-2", "0000000000000002");
HashMap<Class<? extends Configurable>, Configurable> moduleConfigs = new HashMap<>();
moduleConfigs.put(GoogleAnalyticsConfiguration.class, new GoogleAnalyticsConfiguration().setDatasourceIds(dataSourceIds));
ConfigurationProvider.initWithConfig(new CoreConfiguration("FAKE_PROJECT_ID", "FAKE_URL_SCHEME"), moduleConfigs);
spyAdapter = spy(GoogleAnalyticsAdapter.get());
}

@Test
public void newTrackerTest() throws Exception {
String clientId = "1000000000000001";
Tracker tracker = mock(Tracker.class);
when(tracker.get("&cid")).thenReturn(clientId);
CountDownLatch countDownLatch = new CountDownLatch(1);

doAnswer(invocation -> {
Object event = invocation.getArguments()[0];
AnalyticsEvent analyticsEvent = (AnalyticsEvent) event;
JSONObject eventJson = analyticsEvent.toJSONObject();
if (analyticsEvent.getEventType().equals(TrackEventType.LOGIN_USER_ATTRIBUTES)) {
Truth.assertThat(eventJson.getString("dataSourceId")).isEqualTo("0000000000000001");
JSONObject attributes = eventJson.optJSONObject("attributes");
Truth.assertThat(attributes).isNotNull();
Truth.assertThat(attributes.getString("&cid")).isEqualTo("1000000000000001");
countDownLatch.countDown();
}
return invocation.callRealMethod();
}).when(spyAdapter, "postAnalyticsEvent", any(AnalyticsEvent.class));

spyAdapter.newTracker(tracker, 0x00001);
countDownLatch.await(3000, TimeUnit.MILLISECONDS);
}

@Test
public void sendTest() throws Exception {
String measurementId = "UA-000000000-2";
Tracker tracker = mock(Tracker.class);
when(tracker.get("&tid")).thenReturn(measurementId);
spyAdapter.newTracker(tracker, measurementId);

CountDownLatch countDownLatch = new CountDownLatch(1);
doAnswer(invocation -> {
Object event = invocation.getArguments()[0];
AnalyticsEvent analyticsEvent = (AnalyticsEvent) event;
JSONObject eventJson = analyticsEvent.toJSONObject();
if (analyticsEvent.getEventType().equals(TrackEventType.CUSTOM)) {
Truth.assertThat(eventJson.getString("dataSourceId")).isEqualTo("0000000000000002");
JSONObject attributes = eventJson.optJSONObject("attributes");
Truth.assertThat(attributes).isNotNull();
Truth.assertThat(attributes.getString("&ea")).isEqualTo("click");
Truth.assertThat(attributes.getString("&t")).isEqualTo("event");
countDownLatch.countDown();
}
return invocation.callRealMethod();
}).when(spyAdapter, "postAnalyticsEvent", any(AnalyticsEvent.class));

HashMap<String, String> params = new HashMap<>();
params.put("&ea", "click");
params.put("&t", "event");
spyAdapter.send(tracker, params);

countDownLatch.await(3000, TimeUnit.MILLISECONDS);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="ga_trackingId" translatable="false">UA-000000000-1</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ public class EventDataManager {

DeprecatedEventSQLite deprecatedEventSQLite = new DeprecatedEventSQLite(context, this);
deprecatedEventSQLite.migrateEvents();

// when sdk start,removeOverdueEvents
removeOverdueEvents();
}

private EventByteArray formatData(EventFormatData data) {
Expand Down Expand Up @@ -115,7 +118,7 @@ int removeOverdueEvents() {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = getContentUri();
int deleteNum = contentResolver.delete(uri, EventDataTable.COLUMN_CREATE_TIME + "<=" + sevenDayAgo, null);
Logger.e(TAG, "removeOverdueEvents: deleteNum: %d", deleteNum);
Logger.d(TAG, "removeOverdueEvents: num: %d", deleteNum);
return deleteNum;
} catch (SQLiteFullException e) {
onDiskFull(e);
Expand Down Expand Up @@ -241,6 +244,7 @@ private void removeEventById(ContentProviderClient client, long id) throws Remot
} else {
client.delete(uri, COLUMN_ID + "=?", new String[]{String.valueOf(id)});
}
Logger.d(TAG, "removeEventById: id:" + id);
}


Expand All @@ -255,7 +259,7 @@ int removeEvents(long lastId, int policy, String eventType) {
int sum = contentResolver.delete(uri,
COLUMN_ID + "<=? AND " + COLUMN_EVENT_TYPE + "=? AND " + COLUMN_POLICY + "=?",
new String[]{String.valueOf(lastId), eventType, String.valueOf(policy)});
Logger.d(TAG, "removeEvents: deleteNum: %d", sum);
Logger.d(TAG, "removeEvents: num: %d", sum);
return sum;
} catch (SQLiteFullException e) {
onDiskFull(e);
Expand All @@ -276,6 +280,7 @@ void removeAllEvents() {
ContentResolver contentResolver = context.getContentResolver();
Uri uri = getContentUri();
contentResolver.delete(uri, null, null);
Logger.d(TAG, "removeAllEvents success");
} catch (SQLiteFullException e) {
onDiskFull(e);
} catch (Exception e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public Looper getMainLooper() {

@TrackThread
void initSDK() {
mEventSender.removeOverdueEvents();
//mEventSender.removeOverdueEvents();
dispatchActions(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import android.os.Build;
import android.os.Trace;

import com.growingio.android.sdk.track.providers.ConfigurationProvider;

/**
* Just Delegate to Trace
*/
Expand All @@ -28,13 +30,13 @@ private SysTrace() {
}

public static void beginSection(String sectionName) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (ConfigurationProvider.core().isDebugEnabled() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
Trace.beginSection(sectionName);
}
}

public static void endSection() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
if (ConfigurationProvider.core().isDebugEnabled() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
Trace.endSection();
}
}
Expand Down

0 comments on commit 99d5222

Please sign in to comment.