Merge pull request #651 from orbitdb/fix/load-before-append

add multiple tabs in browser test
This commit is contained in:
shamb0t
2019-07-22 20:08:34 +01:00
committed by GitHub
8 changed files with 1449 additions and 893 deletions

View File

@@ -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
View File

@@ -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

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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",

View 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
View 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>

View File

@@ -2,4 +2,5 @@
--colors
--recursive
--exit
--slow 1000
--slow 1000
--exclude test/browser/**/*.js