Skip to content

Commit 50b45b5

Browse files
committed
bl bla
1 parent daa2a89 commit 50b45b5

File tree

5 files changed

+205
-9
lines changed

5 files changed

+205
-9
lines changed

lib/src/database/database_native.dart

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,19 +614,24 @@ class DatabaseNative implements DatabaseInterface {
614614
final dataResult = resultPushPointer.cast<Utf8>().toDartString();
615615

616616
_freeCString!(resultPushPointer);
617-
calloc.free(jsonPointer);
617+
618618

619619
final Map<String, dynamic> response = jsonDecode(dataResult);
620620

621+
622+
621623
if (!response.containsKey('Ok')) {
622624
return Err(ErrorLocalDb.fromRustError(dataResult));
623625
}
624626

627+
// Fix double decode issue - handle both string and object responses
628+
final okData = response['Ok'];
625629
final modelData = LocalDbModel.fromJson(
626-
Map<String, dynamic>.from(jsonDecode(response['Ok'])),
630+
okData is String ? jsonDecode(okData) : okData,
627631
);
628632

629633
return Ok(modelData);
634+
630635
} catch (error, stack) {
631636
Log.e('Error in post operation', error: error, stackTrace: stack);
632637
return Err(
@@ -636,6 +641,9 @@ class DatabaseNative implements DatabaseInterface {
636641
stackTrace: stack,
637642
),
638643
);
644+
} finally {
645+
// Ensure memory cleanup always happens
646+
calloc.free(jsonPointer);
639647
}
640648
}
641649

lib/src/local_db.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ class LocalDB {
161161

162162
final model = LocalDbModel(
163163
id: key,
164-
hash: DateTime.now().millisecondsSinceEpoch.toString(),
165164
data: data,
166165
);
167166

lib/src/model/local_db_request_model.dart

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,23 @@ class LocalDbModel {
2323
/// Converts the model to a JSON map.
2424
///
2525
/// Used for serialization when sending data to the Rust backend.
26-
/// All fields are included in the resulting map.
27-
Map<String, dynamic> toJson() => {
28-
'id': id,
29-
'hash': hash,
30-
'data': data,
31-
};
26+
/// Auto-generates hash from data content if hash is null.
27+
Map<String, dynamic> toJson() {
28+
String finalHash;
29+
30+
if (hash != null) {
31+
finalHash = hash!;
32+
} else {
33+
// Generar hash basado en el contenido de data
34+
finalHash = data.hashCode.toString();
35+
}
36+
37+
return {
38+
'id': id,
39+
'hash': finalHash,
40+
'data': data,
41+
};
42+
}
3243

3344
/// Creates a [LocalDbModel] instance from a JSON map.
3445
///

test/hash_generation_test.dart

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import 'package:flutter_test/flutter_test.dart';
2+
import 'package:flutter_local_db/src/model/local_db_request_model.dart';
3+
4+
void main() {
5+
group('Automatic Hash Generation Tests', () {
6+
test('Should use provided hash when available', () {
7+
final data = {'name': 'Juan', 'age': 25};
8+
final model = LocalDbModel(id: 'test-1', hash: 'custom-hash', data: data);
9+
10+
final json = model.toJson();
11+
12+
expect(json['hash'], 'custom-hash');
13+
expect(json['id'], 'test-1');
14+
expect(json['data'], data);
15+
});
16+
17+
test('Should auto-generate hash from data when hash is null', () {
18+
final data = {'name': 'Juan', 'age': 25};
19+
final model = LocalDbModel(id: 'test-2', data: data);
20+
21+
final json = model.toJson();
22+
23+
// Hash should be auto-generated from data.hashCode
24+
expect(json['hash'], isA<String>());
25+
expect(json['hash'], isNot(equals('null')));
26+
expect(json['hash'], equals(data.hashCode.toString()));
27+
expect(json['id'], 'test-2');
28+
expect(json['data'], data);
29+
30+
print('🎉 Auto-generated hash: ${json['hash']}');
31+
});
32+
33+
test('Should generate consistent hash for same object', () {
34+
final data = {'name': 'Juan', 'age': 25};
35+
36+
final model1 = LocalDbModel(id: 'test-3a', data: data);
37+
final model2 = LocalDbModel(id: 'test-3b', data: data); // Same object reference
38+
39+
final json1 = model1.toJson();
40+
final json2 = model2.toJson();
41+
42+
// Same object should generate same hash
43+
expect(json1['hash'], equals(json2['hash']));
44+
print('🔄 Same object, same hash: ${json1['hash']}');
45+
});
46+
47+
test('Should generate different hash for different data', () {
48+
final data1 = {'name': 'Juan', 'age': 25};
49+
final data2 = {'name': 'Maria', 'age': 30};
50+
51+
final model1 = LocalDbModel(id: 'test-4a', data: data1);
52+
final model2 = LocalDbModel(id: 'test-4b', data: data2);
53+
54+
final json1 = model1.toJson();
55+
final json2 = model2.toJson();
56+
57+
// Different data should generate different hash
58+
expect(json1['hash'], isNot(equals(json2['hash'])));
59+
print('🔀 Different data, different hashes: ${json1['hash']} vs ${json2['hash']}');
60+
});
61+
62+
test('Should work with complex nested data', () {
63+
final complexData = {
64+
'user': {
65+
'name': 'Juan',
66+
'profile': {
67+
'age': 25,
68+
'preferences': ['music', 'sports'],
69+
},
70+
},
71+
'settings': {
72+
'theme': 'dark',
73+
'notifications': true,
74+
},
75+
};
76+
77+
final model = LocalDbModel(id: 'test-complex', data: complexData);
78+
final json = model.toJson();
79+
80+
expect(json['hash'], isA<String>());
81+
expect(json['hash'], equals(complexData.hashCode.toString()));
82+
expect(json['data'], complexData);
83+
84+
print('🧩 Complex data hash: ${json['hash']}');
85+
});
86+
});
87+
}

test/hash_verification_test.dart

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import 'dart:convert';
2+
import 'package:flutter_test/flutter_test.dart';
3+
import 'package:flutter_local_db/src/model/local_db_request_model.dart';
4+
5+
void main() {
6+
group('Hash Verification - toJson() Usage', () {
7+
test('Verify toJson() includes auto-generated hash', () {
8+
print('\n🔍 TESTING ACTUAL toJson() BEHAVIOR');
9+
10+
// Test data without hash
11+
final data = {'name': 'Juan', 'age': 25};
12+
final model = LocalDbModel(id: 'test-user', data: data);
13+
14+
// Convert to JSON like the database does
15+
final json = model.toJson();
16+
final jsonString = jsonEncode(json);
17+
18+
print('📝 Original data: $data');
19+
print('🏷️ Model hash field: ${model.hash}');
20+
print('📤 JSON output: $json');
21+
print('🚀 JSON string to Rust: $jsonString');
22+
23+
// Verify hash was auto-generated
24+
expect(json['hash'], isA<String>());
25+
expect(json['hash'], isNot(equals('null')));
26+
expect(json['hash'], equals(data.hashCode.toString()));
27+
28+
// Verify JSON structure is correct for Rust
29+
expect(json.containsKey('id'), true);
30+
expect(json.containsKey('hash'), true);
31+
expect(json.containsKey('data'), true);
32+
33+
print('✅ Hash auto-generated: ${json['hash']}');
34+
print('✅ JSON structure valid for Rust');
35+
});
36+
37+
test('Verify custom hash is preserved', () {
38+
print('\n🔍 TESTING CUSTOM HASH PRESERVATION');
39+
40+
final data = {'name': 'Maria', 'age': 30};
41+
final model = LocalDbModel(id: 'test-user-2', hash: 'custom-hash-123', data: data);
42+
43+
final json = model.toJson();
44+
final jsonString = jsonEncode(json);
45+
46+
print('📝 Original data: $data');
47+
print('🏷️ Custom hash: custom-hash-123');
48+
print('📤 JSON output: $json');
49+
print('🚀 JSON string to Rust: $jsonString');
50+
51+
// Verify custom hash is used
52+
expect(json['hash'], equals('custom-hash-123'));
53+
expect(json['hash'], isNot(equals(data.hashCode.toString())));
54+
55+
print('✅ Custom hash preserved: ${json['hash']}');
56+
});
57+
58+
test('Verify complex data hash generation', () {
59+
print('\n🔍 TESTING COMPLEX DATA HASH');
60+
61+
final complexData = {
62+
'user': {
63+
'name': 'Carlos',
64+
'profile': {
65+
'age': 35,
66+
'skills': ['Flutter', 'Dart', 'Rust'],
67+
},
68+
},
69+
'metadata': {
70+
'created': '2024-01-01',
71+
'active': true,
72+
},
73+
};
74+
75+
final model = LocalDbModel(id: 'complex-user', data: complexData);
76+
final json = model.toJson();
77+
final jsonString = jsonEncode(json);
78+
79+
print('📝 Complex data keys: ${complexData.keys}');
80+
print('🏷️ Generated hash: ${json['hash']}');
81+
print('📤 JSON length: ${jsonString.length} chars');
82+
print('🚀 JSON preview: ${jsonString.substring(0, 100)}...');
83+
84+
// Verify hash generation for complex data
85+
expect(json['hash'], isA<String>());
86+
expect(json['hash'], equals(complexData.hashCode.toString()));
87+
88+
print('✅ Complex data hash generated successfully');
89+
});
90+
});
91+
}

0 commit comments

Comments
 (0)