mirror of
https://github.com/orbitdb/orbitdb.git
synced 2025-10-07 22:57:07 +00:00
Merge pull request #651 from orbitdb/fix/load-before-append
add multiple tabs in browser test
This commit is contained in:
@@ -76,7 +76,7 @@ jobs:
|
||||
# Test
|
||||
# This would typically be a build job when using workflows, possibly combined with build
|
||||
# The following line was run implicitly in your 1.0 builds based on what CircleCI inferred about the structure of your project. In 2.0 you need to be explicit about which commands should be run. In some cases you can discard inferred commands if they are not relevant to your project.
|
||||
- run: npm test
|
||||
- run: npm run test:all
|
||||
# Teardown
|
||||
# If you break your build into multiple jobs with workflows, you will probably want to do the parts of this that are relevant in each
|
||||
# Save test results
|
||||
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -4,6 +4,15 @@ orbitdb/
|
||||
# Don't distribute the dependencies
|
||||
node_modules/
|
||||
|
||||
#Don't track ipfs files
|
||||
test/ipfs/
|
||||
test/browser/ipfs/
|
||||
test/browser/orbitdb/
|
||||
test/browser/orbitdb.js
|
||||
test/browser/ipfs.js
|
||||
test/browser/ipfslog.min.js
|
||||
test/browser/identities.js
|
||||
|
||||
# Don't track examples' dependencies (libs) in git
|
||||
examples/browser/browser-webpack-example/bundle.js
|
||||
examples/browser/browser-webpack-example/*.map
|
||||
|
||||
2
Makefile
2
Makefile
@@ -4,7 +4,7 @@ deps:
|
||||
npm install
|
||||
|
||||
test: deps
|
||||
npm run test
|
||||
npm run test:all
|
||||
|
||||
build: test
|
||||
mkdir -p examples/browser/lib/
|
||||
|
||||
2106
package-lock.json
generated
2106
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@
|
||||
"babel-preset-env": "^1.7.0",
|
||||
"datastore-level": "0.10.0",
|
||||
"fs-extra": "^7.0.1",
|
||||
"go-ipfs-dep": "0.4.19",
|
||||
"go-ipfs-dep": "~0.4.20",
|
||||
"ipfs": "~0.36.4",
|
||||
"ipfs-repo": "~0.26.6",
|
||||
"ipfsd-ctl": "~0.42.3",
|
||||
@@ -51,6 +51,7 @@
|
||||
"p-map-series": "^1.0.0",
|
||||
"p-whilst": "^1.0.0",
|
||||
"pify": "^4.0.1",
|
||||
"puppeteer": "^1.18.1",
|
||||
"remark-cli": "^5.0.0",
|
||||
"remark-validate-links": "^7.0.0",
|
||||
"rimraf": "^2.6.2",
|
||||
@@ -63,7 +64,9 @@
|
||||
"examples:browser-macos": "open examples/browser/browser.html",
|
||||
"examples:browser-linux": "xdg-open examples/browser/browser.html",
|
||||
"lint:docs": "remark -qf -u validate-links .",
|
||||
"test:all": "npm run test:browser-multiple-tabs && npm run test",
|
||||
"test": "TEST=all mocha",
|
||||
"test:browser-multiple-tabs": "npm run build:dist && cp dist/orbitdb.min.js ./test/browser/orbitdb.js && cp node_modules/ipfs/dist/index.js ./test/browser/ipfs.js && cp node_modules/orbit-db-identity-provider/dist/index-browser.min.js ./test/browser/identities.js && cp node_modules/ipfs-log/dist/ipfslog.min.js ./test/browser/ipfslog.min.js && mocha ./test/browser/concurrent.spec.js",
|
||||
"build": "npm run build:es5 && npm run build:debug && npm run build:dist && npm run build:examples && npm run build:docs/toc",
|
||||
"build:examples": "webpack --config conf/webpack.example.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp node_modules/ipfs/dist/index.js examples/browser/lib/ipfs.js",
|
||||
"build:dist": "webpack --config conf/webpack.config.js --sort-modules-by size && mkdir -p examples/browser/lib && cp dist/orbitdb.min.js examples/browser/lib/orbitdb.min.js",
|
||||
|
||||
121
test/browser/concurrent.spec.js
Normal file
121
test/browser/concurrent.spec.js
Normal file
@@ -0,0 +1,121 @@
|
||||
'use strict'
|
||||
const assert = require('assert')
|
||||
const puppeteer = require('puppeteer')
|
||||
const path = require('path')
|
||||
const mapSeries = require('p-map-series')
|
||||
const pMap = require('p-map')
|
||||
const {
|
||||
config,
|
||||
} = require('../utils')
|
||||
|
||||
const clicksPerTab = 20
|
||||
const numTabs = 3
|
||||
|
||||
describe(`orbit-db - browser concurrent writes`, function() {
|
||||
this.timeout(numTabs * config.timeout)
|
||||
|
||||
let browser
|
||||
const options = {
|
||||
ignoreHTTPSErrors: true,
|
||||
args: ['--no-sandbox', '--disable-setuid-sandbox']
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
browser = await puppeteer.launch(options)
|
||||
})
|
||||
|
||||
after(async () => {
|
||||
await browser.close()
|
||||
})
|
||||
|
||||
describe('Write concurrently', function() {
|
||||
let tabs = []
|
||||
before(async () => {
|
||||
const createTab = async () => {
|
||||
const page = await browser.newPage()
|
||||
await page.goto(`file://${path.resolve(__dirname, 'index.html')}`)
|
||||
page.on('dialog', dialog => dialog.dismiss())
|
||||
page.on('pageerror', err => console.error(err))
|
||||
return page
|
||||
}
|
||||
|
||||
// open several tabs
|
||||
for (let i = 0; i < numTabs; i++) {
|
||||
const tab = await createTab()
|
||||
tabs.push(tab)
|
||||
}
|
||||
|
||||
const addDataButton = 'button#addData'
|
||||
await pMap(tabs, async (page) => {
|
||||
await page.waitForFunction(
|
||||
'document.querySelector("#waitForOpenDB").innerText.includes("orbitdb")'
|
||||
)
|
||||
const addDataToLog = (maxClicks, maxWaitTime) => {
|
||||
let count = 0
|
||||
const repeat = () => new Promise((resolve, reject) => {
|
||||
setTimeout(async () => {
|
||||
await page.click(addDataButton)
|
||||
if (++count < maxClicks) {
|
||||
await repeat()
|
||||
}
|
||||
resolve()
|
||||
}, Math.random() * maxWaitTime + 300) // ensure waiting at least ~300ms
|
||||
})
|
||||
return repeat()
|
||||
}
|
||||
|
||||
return addDataToLog(clicksPerTab, 1000)
|
||||
})
|
||||
})
|
||||
|
||||
it('syncLocal option - Multiple tabs converge to same log', async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
let polls = 0
|
||||
const interval = setInterval(async () => {
|
||||
let logHashes = []
|
||||
await mapSeries(tabs, async (page) => {
|
||||
await page.evaluate(() => loadLogs())
|
||||
const hash = await page.evaluate(async () => await getConsistentLogHash())
|
||||
logHashes.push(hash)
|
||||
})
|
||||
|
||||
try {
|
||||
const hashes = Array.from(new Set(logHashes))
|
||||
// ensure log hashes are equal
|
||||
assert.strictEqual(hashes.length, 1)
|
||||
clearInterval(interval)
|
||||
resolve()
|
||||
} catch (e) {
|
||||
console.log("Repolling...")
|
||||
if (++polls > 5) {
|
||||
reject(e)
|
||||
}
|
||||
}
|
||||
}, 3000)
|
||||
})
|
||||
})
|
||||
|
||||
it('no syncLocal option - Multiple tabs do not converge to same log', async () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const interval = setInterval(async () => {
|
||||
let logHashes = []
|
||||
await mapSeries(tabs, async (page) => {
|
||||
await page.evaluate(() => loadLogs())
|
||||
const hash = await page.evaluate(async () => await getInconsistentLogHash())
|
||||
logHashes.push(hash)
|
||||
})
|
||||
|
||||
try {
|
||||
const hashes = Array.from(new Set(logHashes))
|
||||
// logs hash different hashes
|
||||
assert.strictEqual(hashes.length, numTabs)
|
||||
clearInterval(interval)
|
||||
resolve()
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
}, 3000)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
94
test/browser/index.html
Normal file
94
test/browser/index.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Break OrbitDB</title>
|
||||
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
|
||||
<meta content="utf-8" http-equiv="encoding">
|
||||
<script type="text/javascript" src="orbitdb.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="ipfs.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="identities.js" charset="utf-8"></script>
|
||||
<script type="text/javascript" src="ipfslog.min.js" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="padding: 0px 0px 25px 0px;">
|
||||
<p>
|
||||
<span id="waitForOpenDB"></span>
|
||||
</p>
|
||||
<button id="addData" type="button">Add random data</button>
|
||||
<hr />
|
||||
<h3> Log Data </h3>
|
||||
<p>
|
||||
<span id="logData"></span>
|
||||
</p>
|
||||
</div>
|
||||
<!-- </div> -->
|
||||
<script type="text/javascript">
|
||||
const randStr = () => Math.random().toString(36).substring(6)
|
||||
const ipfs = new Ipfs({
|
||||
repo: './odb/',
|
||||
EXPERIMENTAL: {
|
||||
pubsub: true
|
||||
},
|
||||
preload: { enabled: false },
|
||||
config: {
|
||||
Bootstrap: [ ]
|
||||
}
|
||||
})
|
||||
|
||||
async function getConsistentLogLength () {
|
||||
return window.consistentLog._oplog.length
|
||||
}
|
||||
|
||||
async function getConsistentLogHash () {
|
||||
return await window.consistentLog._oplog.toMultihash()
|
||||
}
|
||||
|
||||
async function getConsistentEntries () {
|
||||
return window.consistentLog.iterator({ limit: -1 }).collect()
|
||||
}
|
||||
|
||||
async function getInconsistentLogLength () {
|
||||
return window.inconsistentLog._oplog.length
|
||||
}
|
||||
|
||||
async function getInconsistentLogHash () {
|
||||
return await window.inconsistentLog._oplog.toMultihash()
|
||||
}
|
||||
|
||||
async function getInconsistentEntries () {
|
||||
return window.inconsistentLog.iterator({ limit: -1 }).collect()
|
||||
}
|
||||
|
||||
async function loadLogs () {
|
||||
await window.consistentLog.load()
|
||||
await window.inconsistentLog.load()
|
||||
}
|
||||
|
||||
ipfs.on('ready', async () => {
|
||||
const identity = await Identities.createIdentity({ id: 'A'})
|
||||
const orbitdb = await OrbitDB.createInstance(ipfs, { identity })
|
||||
const consistentLog = await orbitdb.log('concurrent', { syncLocal: true, sortFn: Log.Sorting.SortByEntryHash })
|
||||
const inconsistentLog = await orbitdb.log('concurrent2')
|
||||
|
||||
window.consistentLog = consistentLog
|
||||
window.inconsistentLog = inconsistentLog
|
||||
|
||||
waitForOpenDB.innerHTML = consistentLog.address.toString() + ' + ' + inconsistentLog.address.toString()
|
||||
await consistentLog.load()
|
||||
await inconsistentLog.load()
|
||||
|
||||
// const updateData = () => {
|
||||
// logData.innerHTML = ''
|
||||
// const count = consistentlog.iterator({ limit: -1 }).collect().map(e => {
|
||||
// logData.innerHTML += e.clock.time + ': ' + e.hash + '<br />'
|
||||
// })
|
||||
// }
|
||||
|
||||
addData.addEventListener('click', async event => {
|
||||
const data = randStr()
|
||||
await consistentLog.add(data)
|
||||
await inconsistentLog.add(data)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -2,4 +2,5 @@
|
||||
--colors
|
||||
--recursive
|
||||
--exit
|
||||
--slow 1000
|
||||
--slow 1000
|
||||
--exclude test/browser/**/*.js
|
||||
|
||||
Reference in New Issue
Block a user