Skip to content

Commit

Permalink
sparql-proxy: add some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ludovicm67 committed Aug 27, 2024
1 parent 79a91eb commit 21d81bc
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 17 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 12 additions & 17 deletions packages/sparql-proxy/lib/ReplaceStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,40 +6,35 @@ class ReplaceStream extends Transform {
this.searchStr = searchStr
this.replaceStr = replaceStr
this.tailPiece = '' // Holds trailing data from previous chunk
this.searchStrLen = searchStr.length
}

_transform (chunk, encoding, callback) {
const data = this.tailPiece + chunk.toString() // Combine previous tail with new chunk
let lastIndex = 0
let index

// Array to hold the processed pieces
const processedPieces = []
const pieces = []

let index
// Search for the searchStr in the data
// Search for occurrences of searchStr
while ((index = data.indexOf(this.searchStr, lastIndex)) !== -1) {
// Push the data before the match and the replacement string
processedPieces.push(data.slice(lastIndex, index))
processedPieces.push(this.replaceStr)
lastIndex = index + this.searchStr.length
pieces.push(data.slice(lastIndex, index)) // Push the data before the match
pieces.push(this.replaceStr) // Push the replacement string
lastIndex = index + this.searchStrLen // Move the index past the match
}

// Save the remaining data in tailPiece
// Save the remaining data after the last match as tailPiece
this.tailPiece = data.slice(lastIndex)

// Push the processed pieces
this.push(processedPieces.join(''))
// Push the processed data
this.push(pieces.join(''))

callback()
}

_flush (callback) {
// Handle any remaining data in tailPiece
if (this.tailPiece.includes(this.searchStr)) {
this.push(this.tailPiece.replace(this.searchStr, this.replaceStr))
} else {
this.push(this.tailPiece)
}
// Push out any remaining data in tailPiece, processing any matches in it
this.push(this.tailPiece.replace(new RegExp(this.searchStr, 'g'), this.replaceStr))
callback()
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/sparql-proxy/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"devDependencies": {
"@types/node": "^22.4.1",
"chai": "^5.1.1",
"mocha": "^10.7.3",
"sinon": "^18.0.0",
"sinon-chai": "^4.0.0"
},
Expand Down
137 changes: 137 additions & 0 deletions packages/sparql-proxy/test/ReplaceStream.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { PassThrough } from 'node:stream'
import { expect } from 'chai'
import { describe, it } from 'mocha'
import ReplaceStream from '../lib/ReplaceStream.js'

describe('ReplaceStream', () => {
it('should replace a single occurrence of a string', (done) => {
const replaceStream = new ReplaceStream('old', 'new')
const input = new PassThrough()
const output = new PassThrough()

const receivedData = []

input.pipe(replaceStream).pipe(output)

output.setEncoding('utf8')
output.on('data', (data) => {
receivedData.push(data)
})

output.on('end', () => {
expect(receivedData.join('')).to.equal('new string')
done()
})

input.write('old string')
input.end()
})

it('should replace multiple occurrences of a string', (done) => {
const replaceStream = new ReplaceStream('old', 'new')
const input = new PassThrough()
const output = new PassThrough()

const receivedData = []

input.pipe(replaceStream).pipe(output)

output.setEncoding('utf8')
output.on('data', (data) => {
receivedData.push(data)
})

output.on('end', () => {
expect(receivedData.join('')).to.equal('new string with new value')
done()
})

input.write('old string with old value')
input.end()
})

it('should replace strings that span across chunks', (done) => {
const replaceStream = new ReplaceStream('old', 'new')
const input = new PassThrough()
const output = new PassThrough()

const receivedData = []

input.pipe(replaceStream).pipe(output)

output.setEncoding('utf8')
output.on('data', (data) => {
receivedData.push(data)
})

output.on('end', () => {
expect(receivedData.join('')).to.equal('new and new')
done()
})

input.write('ol')
input.write('d and ol')
input.write('d')
input.end()
})

it('should handle no occurrences of the string', (done) => {
const replaceStream = new ReplaceStream('old', 'new')
const input = new PassThrough()
const output = new PassThrough()

input.pipe(replaceStream).pipe(output)

output.setEncoding('utf8')
output.on('data', (data) => {
expect(data).to.equal('no match here')
})

output.on('end', done)

input.write('no match here')
input.end()
})

it('should handle empty input', (done) => {
const replaceStream = new ReplaceStream('old', 'new')
const input = new PassThrough()
const output = new PassThrough()

input.pipe(replaceStream).pipe(output)

output.setEncoding('utf8')
output.on('data', (data) => {
expect(data).to.equal('')
})

output.on('end', done)

input.end()
})

it('should handle large input with multiple replacements', (done) => {
const replaceStream = new ReplaceStream('old', 'new')
const input = new PassThrough()
const output = new PassThrough()

const largeInput = 'old '.repeat(1000)
const expectedOutput = 'new '.repeat(1000)

input.pipe(replaceStream).pipe(output)

let result = ''
output.setEncoding('utf8')
output.on('data', (data) => {
result += data
})

output.on('end', () => {
expect(result).to.equal(expectedOutput)
done()
})

input.write(largeInput)
input.end()
})
})

0 comments on commit 21d81bc

Please sign in to comment.