Skip to content

Error handling for malformed session file #38

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkgs/unified_analytics/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 0.1.3-dev

- Error handling functionality added to prevent malformed session json data from causing a crash
- Creating a new analytics constructor to point to a test instance of Google Analytics for developers

## 0.1.2
Expand Down
5 changes: 3 additions & 2 deletions pkgs/unified_analytics/lib/src/initializer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ $tool=$dateStamp,$toolsMessageVersion
/// the current session id along with the timestamp for
/// the last ping which will be used to increment the session
/// if current timestamp is greater than the session window
void createSessionFile({required File sessionFile}) {
static void createSessionFile({required File sessionFile}) {
final DateTime now = clock.now();
sessionFile.createSync(recursive: true);
sessionFile.writeAsStringSync(jsonEncode(<String, int>{
Expand All @@ -91,7 +91,8 @@ $tool=$dateStamp,$toolsMessageVersion
/// If it doesn't exist, one will be created there
///
/// Passing [forceReset] as true will only reset the configuration
/// file, it won't recreate the client id and session files
/// file, it won't recreate the client id, session, and log files
/// if they currently exist on disk.
void run({bool forceReset = false}) {
// Begin by checking for the config file
final File configFile = fs.file(
Expand Down
61 changes: 23 additions & 38 deletions pkgs/unified_analytics/lib/src/session.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,48 +9,23 @@ import 'package:file/file.dart';
import 'package:path/path.dart' as p;

import 'constants.dart';
import 'initializer.dart';

class Session {
final Directory homeDirectory;
final FileSystem fs;
final File _sessionFile;
int _sessionId;
int _lastPing;

/// This constructor will go to the session json file in
/// the user's home directory and extract the necessary fields from
/// the json file
factory Session({
required Directory homeDirectory,
required FileSystem fs,
}) {
final File sessionFile = fs.file(
p.join(homeDirectory.path, kDartToolDirectoryName, kSessionFileName));
late int _sessionId;
late int _lastPing;

final String sessionFileContents = sessionFile.readAsStringSync();
final Map<String, Object?> sessionObj = jsonDecode(sessionFileContents);
final int sessionId = sessionObj['session_id'] as int;
final int lastPing = sessionObj['last_ping'] as int;

return Session._(
homeDirectory: homeDirectory,
fs: fs,
sessionFile: sessionFile,
sessionId: sessionId,
lastPing: lastPing,
);
}

/// Private constructor that will have the variables necessary already parsed
Session._({
Session({
required this.homeDirectory,
required this.fs,
required File sessionFile,
required int sessionId,
required int lastPing,
}) : _sessionFile = sessionFile,
_sessionId = sessionId,
_lastPing = lastPing;
}) : _sessionFile = fs.file(p.join(
homeDirectory.path, kDartToolDirectoryName, kSessionFileName)) {
_refreshSessionData();
}

/// This will use the data parsed from the
/// session json file in the dart-tool directory
Expand Down Expand Up @@ -94,15 +69,25 @@ class Session {

/// This will go to the session file within the dart-tool
/// directory and fetch the latest data from the json to update
/// the class's variables
/// the class's variables. If the json file is malformed, a new
/// session file will be recreated
///
/// This allows the session data in this class to always be up
/// to date incase another tool is also calling this package and
/// making updates to the session file
void _refreshSessionData() {
final String sessionFileContents = _sessionFile.readAsStringSync();
final Map<String, Object?> sessionObj = jsonDecode(sessionFileContents);
_sessionId = sessionObj['session_id'] as int;
_lastPing = sessionObj['last_ping'] as int;
try {
final String sessionFileContents = _sessionFile.readAsStringSync();
final Map<String, Object?> sessionObj = jsonDecode(sessionFileContents);
_sessionId = sessionObj['session_id'] as int;
_lastPing = sessionObj['last_ping'] as int;
} on FormatException {
Initializer.createSessionFile(sessionFile: _sessionFile);

final String sessionFileContents = _sessionFile.readAsStringSync();
final Map<String, Object?> sessionObj = jsonDecode(sessionFileContents);
_sessionId = sessionObj['session_id'] as int;
_lastPing = sessionObj['last_ping'] as int;
}
}
}
18 changes: 18 additions & 0 deletions pkgs/unified_analytics/test/unified_analytics_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,24 @@ void main() {
'for the initialized tool');
});

test('Resetting session file when data is malformed', () {
// Purposefully write content to the session file that
// can't be decoded as json
sessionFile.writeAsStringSync('contents');

// Define the initial time to start
final DateTime start = DateTime(1995, 3, 3, 12, 0);

// Set the clock to the start value defined above
withClock(Clock.fixed(start), () {
final String timestamp = clock.now().millisecondsSinceEpoch.toString();
expect(sessionFile.readAsStringSync(), 'contents');
userProperty.preparePayload();
expect(sessionFile.readAsStringSync(),
'{"session_id":$timestamp,"last_ping":$timestamp}');
});
});

test('New tool is successfully added to config file', () {
// Create a new instance of the analytics class with the new tool
final Analytics secondAnalytics = Analytics.test(
Expand Down