Skip to content

Commit

Permalink
selfTest simulate scenario in BUG storesafe#666
Browse files Browse the repository at this point in the history
Includes string test and test of effects of location reload/change
in this version branch
  • Loading branch information
Christopher J. Brody committed Apr 19, 2017
1 parent 8fd7846 commit 42a98fb
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 15 deletions.
3 changes: 2 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Changes

### cordova-sqlite-legacy-express-core 1.0.0-pre1
### cordova-sqlite-legacy-express-core 1.0.0-pre2

- selfTest simulate scenario in BUG litehelpers/Cordova-sqlite-storage#666 (includes string test and test of effects of location reload/change in this version branch)
- Drop engine constraints in package.json & plugin.xml (in this version branch)
- Support macOS platform with builtin libsqlite3.dylib framework in this version branch

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ Some other projects by [@brodybits](https://github.com/brodybits):
- As described in [this posting](http://brodyspark.blogspot.com/2012/12/cordovaphonegap-sqlite-plugins-offer.html):
- Keeps sqlite database in a user data location that is known; can be reconfigured (iOS/macOS platform version); and may be synchronized to iCloud (iOS version).
- No 5MB maximum, more information at: http://www.sqlite.org/limits.html
- Also tested for multi-page applications with window location changes
- This project is self-contained: no dependencies on other plugins such as cordova-plugin-file
- Windows 10 UWP platform version available in [litehelpers / cordova-sqlite-ext](https://github.com/litehelpers/cordova-sqlite-ext) and Windows 8.1/Windows Phone 8.1/Windows 10 platform version available in [litehelpers / Cordova-sqlite-legacy](https://github.com/litehelpers/Cordova-sqlite-legacy) use the performant C++ [doo / SQLite3-WinRT](https://github.com/doo/SQLite3-WinRT) component.
- [SQLCipher](https://www.zetetic.net/sqlcipher/) support for Android/iOS/macOS/Windows is available in: [litehelpers / Cordova-sqlcipher-adapter](https://github.com/litehelpers/Cordova-sqlcipher-adapter)
Expand All @@ -124,6 +125,7 @@ Some other projects by [@brodybits](https://github.com/brodybits):

## Known issues

- Transaction problem after page change WITH POSSIBLE DATA LOSS ref: [litehelpers/Cordova-sqlite-storage#666](https://github.com/litehelpers/Cordova-sqlite-storage/issues/666)
- iOS/macOS platform version does not support certain rapidly repeated open-and-close or open-and-delete test scenarios due to how the implementation handles background processing
- As described below, auto-vacuum is NOT enabled by default.
- INSERT statement that affects multiple rows (due to SELECT cause or using TRIGGER(s), for example) does not report proper rowsAffected on Android
Expand Down Expand Up @@ -163,7 +165,6 @@ Some other projects by [@brodybits](https://github.com/brodybits):
## Further testing needed

- Integration with PhoneGap developer app
- Multi-page apps
- Use within [InAppBrowser](http://docs.phonegap.com/en/edge/cordova_inappbrowser_inappbrowser.md.html)
- Use within an iframe (see [litehelpers/Cordova-sqlite-storage#368 (comment)](https://github.com/litehelpers/Cordova-sqlite-storage/issues/368#issuecomment-154046367))
- Actual behavior when using SAVEPOINT(s)
Expand Down
120 changes: 117 additions & 3 deletions SQLitePlugin.coffee.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
# applications that repeatedly open and close the database.
# [BUG #210] TODO: better to abort and clean up the pending transaction state.
# XXX TBD this will be renamed and include some more per-db state.
# NOTE: In case txLocks is renamed or replaced the selfTest has to be adapted as well.
txLocks = {}

## utility functions:
Expand Down Expand Up @@ -116,6 +117,7 @@
# Keep track of state of open db connections
# XXX TBD this will be moved and renamed or
# combined with txLocks.
# NOTE: In case txLocks is renamed or replaced the selfTest has to be adapted as well.
SQLitePlugin::openDBs = {}

SQLitePlugin::addTransaction = (t) ->
Expand Down Expand Up @@ -690,11 +692,121 @@

start: (successcb, errorcb) ->
SQLiteFactory.deleteDatabase {name: SelfTest.DBNAME, location: 'default'},
(-> SelfTest.start2(successcb, errorcb)),
(-> SelfTest.start2(successcb, errorcb))
(-> SelfTest.step1(successcb, errorcb)),
(-> SelfTest.step1(successcb, errorcb))
return

step1: (successcb, errorcb) ->
SQLiteFactory.openDatabase {name: SelfTest.DBNAME, location: 'default'}, (db) ->
check1 = false
db.transaction (tx) ->
tx.executeSql 'SELECT UPPER("Test") AS upperText', [], (ignored, resutSet) ->
if !resutSet.rows
return SelfTest.finishWithError errorcb, 'Missing resutSet.rows'

if !resutSet.rows.length
return SelfTest.finishWithError errorcb, 'Missing resutSet.rows.length'

if resutSet.rows.length isnt 1
return SelfTest.finishWithError errorcb,
"Incorrect resutSet.rows.length value: #{resutSet.rows.length} (expected: 1)"

if !resutSet.rows.item(0).upperText
return SelfTest.finishWithError errorcb,
'Missing resutSet.rows.item(0).upperText'

if resutSet.rows.item(0).upperText isnt 'TEST'
return SelfTest.finishWithError errorcb,
"Incorrect resutSet.rows.item(0).upperText value: #{resutSet.rows.item(0).upperText} (expected: 'TEST')"

check1 = true
return

, (ignored, tx_sql_err) ->
return SelfTest.finishWithError errorcb, "TX SQL error: #{tx_sql_err}"

return

, (tx_err) ->
return SelfTest.finishWithError errorcb, "TRANSACTION error: #{tx_err}"

, () ->
# tx success:
if !check1
return SelfTest.finishWithError errorcb,
'Did not get expected upperText result data'

# SIMULATE SCENARIO IN BUG litehelpers/Cordova-sqlite-storage#666:
db.executeSql 'BEGIN', null, (ignored) -> nextTick -> # (nextTick needed for Windows)
# DELETE INTERNAL STATE to simulate the effects of location refresh or change:
delete db.openDBs[SelfTest.DBNAME]
delete txLocks[SelfTest.DBNAME]

# VERIFY INTERNAL STATE IS DELETED:
try
# EXPECTED TO THROW:
db.transaction (tx2) ->
tx2.executeSql 'SELECT 1'
return
# SHOULD NOT GET HERE:
return SelfTest.finishWithError errorcb, 'db.transaction DID NOT THROW after INTERNAL STATE IS DELETED'
catch e
# EXPECTED:
if !e
return SelfTest.finishWithError errorcb, 'Missing exception object'
SelfTest.step2 successcb, errorcb
return
return
return

, (open_err) ->
SelfTest.finishWithError errorcb, "Open database error: #{open_err}"
return

start2: (successcb, errorcb) ->
step2: (successcb, errorcb) ->
SQLiteFactory.openDatabase {name: SelfTest.DBNAME, location: 'default'}, (db) ->
db.transaction (tx) ->
tx.executeSql 'SELECT ? AS myResult', [null], (ignored, resutSet) ->
# Extra sql success callback ignored:
return
return

, (txError) ->
# EXPECTED RESULT DUE TO BUG litehelpers/Cordova-sqlite-storage#666:
if !txError
return SelfTest.finishWithError errorcb, 'Missing txError object'
# second try should work:
db.transaction (tx2) ->
tx2.executeSql 'SELECT ? AS myResult', [null], (ignored, resutSet) ->
if !resutSet.rows
return SelfTest.finishWithError errorcb, 'Missing resutSet.rows'
if !resutSet.rows.length
return SelfTest.finishWithError errorcb, 'Missing resutSet.rows.length'
if resutSet.rows.length isnt 1
return SelfTest.finishWithError errorcb,
SelfTest.step3 successcb, errorcb
return
return
, (tx2_err) ->
return SelfTest.finishWithError errorcb, "UNEXPECTED TRANSACTION ERROR: #{tx2_err}"
return

, () ->
# TX SUCCESS POSSIBLE FOR Android (android.database) ONLY:
if /Android/.test(navigator.userAgent) and not /Windows /.test(navigator.userAgent)
return SelfTest.step3 successcb, errorcb
# OTHERWISE:
# TX SUCCESS NOT EXPECTED DUE TO BUG litehelpers/Cordova-sqlite-storage#666:
return SelfTest.finishWithError errorcb, 'UNEXPECTED SUCCESS ref: litehelpers/Cordova-sqlite-storage#666'
return

, (open_err) ->
SelfTest.finishWithError errorcb, "Open database error: #{open_err}"
return

step3: (successcb, errorcb) ->
SQLiteFactory.openDatabase {name: SelfTest.DBNAME, location: 'default'}, (db) ->
# FUTURE TBD TEST CRUD OPERATIONS (already fixed in a newer version branch)
db.sqlBatch [
'CREATE TABLE TestTable(TestColumn);'
[ 'INSERT INTO TestTable (TestColumn) VALUES (?);', ['test-value'] ]
Expand Down Expand Up @@ -764,11 +876,13 @@

, (open_err) ->
SelfTest.finishWithError errorcb, "Open database error: #{open_err}"
return

finishWithError: (errorcb, message) ->
SQLiteFactory.deleteDatabase {name: SelfTest.DBNAME, location: 'default'}, ->
errorcb newSQLError message
, (err2)-> errorcb newSQLError "Cleanup error: #{err2} for error: #{message}"
return

## Exported API:

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cordova-sqlite-legacy-express-core",
"version": "1.0.0-pre1",
"version": "1.0.0-pre2",
"description": "Native interface to SQLite for PhoneGap/Cordova (legacy express core version)",
"cordova": {
"id": "cordova-sqlite-legacy-express-core",
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<plugin xmlns="http://www.phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-sqlite-legacy-express-core"
version="1.0.0-pre1">
version="1.0.0-pre2">

<name>Cordova sqlite storage plugin - express core version</name>

Expand Down
111 changes: 103 additions & 8 deletions www/SQLitePlugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@
};

SQLitePluginTransaction.prototype.start = function() {
var err, error1;
var err;
try {
this.fn(this);
this.run();
Expand Down Expand Up @@ -402,7 +402,7 @@
tx = this;
handlerFor = function(index, didSucceed) {
return function(response) {
var err, error1;
var err;
try {
if (didSucceed) {
tx.handleStatementSuccess(batchExecutes[index].success, response);
Expand Down Expand Up @@ -606,17 +606,112 @@
SelfTest = {
DBNAME: '___$$$___litehelpers___$$$___test___$$$___.db',
start: function(successcb, errorcb) {
return SQLiteFactory.deleteDatabase({
SQLiteFactory.deleteDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, (function() {
return SelfTest.start2(successcb, errorcb);
return SelfTest.step1(successcb, errorcb);
}), (function() {
return SelfTest.start2(successcb, errorcb);
return SelfTest.step1(successcb, errorcb);
}));
},
start2: function(successcb, errorcb) {
return SQLiteFactory.openDatabase({
step1: function(successcb, errorcb) {
SQLiteFactory.openDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, function(db) {
var check1;
check1 = false;
db.transaction(function(tx) {
tx.executeSql('SELECT UPPER("Test") AS upperText', [], function(ignored, resutSet) {
if (!resutSet.rows) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows');
}
if (!resutSet.rows.length) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.length');
}
if (resutSet.rows.length !== 1) {
return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.length value: " + resutSet.rows.length + " (expected: 1)");
}
if (!resutSet.rows.item(0).upperText) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.item(0).upperText');
}
if (resutSet.rows.item(0).upperText !== 'TEST') {
return SelfTest.finishWithError(errorcb, "Incorrect resutSet.rows.item(0).upperText value: " + (resutSet.rows.item(0).upperText) + " (expected: 'TEST')");
}
check1 = true;
}, function(ignored, tx_sql_err) {
return SelfTest.finishWithError(errorcb, "TX SQL error: " + tx_sql_err);
});
}, function(tx_err) {
return SelfTest.finishWithError(errorcb, "TRANSACTION error: " + tx_err);
}, function() {
if (!check1) {
return SelfTest.finishWithError(errorcb, 'Did not get expected upperText result data');
}
db.executeSql('BEGIN', null, function(ignored) {
return nextTick(function() {
var e;
delete db.openDBs[SelfTest.DBNAME];
delete txLocks[SelfTest.DBNAME];
try {
db.transaction(function(tx2) {
tx2.executeSql('SELECT 1');
});
return SelfTest.finishWithError(errorcb, 'db.transaction DID NOT THROW after INTERNAL STATE IS DELETED');
} catch (error1) {
e = error1;
if (!e) {
return SelfTest.finishWithError(errorcb, 'Missing exception object');
}
SelfTest.step2(successcb, errorcb);
}
});
});
});
}, function(open_err) {
return SelfTest.finishWithError(errorcb, "Open database error: " + open_err);
});
},
step2: function(successcb, errorcb) {
SQLiteFactory.openDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, function(db) {
db.transaction(function(tx) {
tx.executeSql('SELECT ? AS myResult', [null], function(ignored, resutSet) {});
}, function(txError) {
if (!txError) {
return SelfTest.finishWithError(errorcb, 'Missing txError object');
}
db.transaction(function(tx2) {
tx2.executeSql('SELECT ? AS myResult', [null], function(ignored, resutSet) {
if (!resutSet.rows) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows');
}
if (!resutSet.rows.length) {
return SelfTest.finishWithError(errorcb, 'Missing resutSet.rows.length');
}
if (resutSet.rows.length !== 1) {
return SelfTest.finishWithError(errorcb);
}
SelfTest.step3(successcb, errorcb);
});
}, function(tx2_err) {
return SelfTest.finishWithError(errorcb, "UNEXPECTED TRANSACTION ERROR: " + tx2_err);
});
}, function() {
if (/Android/.test(navigator.userAgent) && !/Windows /.test(navigator.userAgent)) {
return SelfTest.step3(successcb, errorcb);
}
return SelfTest.finishWithError(errorcb, 'UNEXPECTED SUCCESS ref: litehelpers/Cordova-sqlite-storage#666');
});
}, function(open_err) {
return SelfTest.finishWithError(errorcb, "Open database error: " + open_err);
});
},
step3: function(successcb, errorcb) {
SQLiteFactory.openDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, function(db) {
Expand Down Expand Up @@ -691,7 +786,7 @@
});
},
finishWithError: function(errorcb, message) {
return SQLiteFactory.deleteDatabase({
SQLiteFactory.deleteDatabase({
name: SelfTest.DBNAME,
location: 'default'
}, function() {
Expand Down

0 comments on commit 42a98fb

Please sign in to comment.