<commit_before>/* eslint-env mocha */
'use strict'

const { getDescribe, getIt, expect } = require('../utils/mocha')

module.exports = (createCommon, options) => {
  const describe = getDescribe(options)
  const it = getIt(options)
  const common = createCommon()

  describe('.repo.gc', () => {
    let ipfs

    before(function (done) {
      // CI takes longer to instantiate the daemon, so we need to increase the
      // timeout for the before step
      this.timeout(60 * 1000)

      common.setup((err, factory) => {
        expect(err).to.not.exist()
        factory.spawnNode((err, node) => {
          expect(err).to.not.exist()
          ipfs = node
          done()
        })
      })
    })

    after((done) => common.teardown(done))

    it('should run garbage collection', (done) => {
      ipfs.repo.gc((err, res) => {
        expect(err).to.not.exist()
        expect(res).to.exist()
        done()
      })
    })

    it('should run garbage collection (promised)', () => {
      return ipfs.repo.gc().then((res) => {
        expect(res).to.exist()
      })
    })
  })
}
<commit_msg>test: add tests for garbage collection (#462)<commit_after>/* eslint-env mocha */
'use strict'

const { getDescribe, getIt, expect } = require('../utils/mocha')
const { DAGNode } = require('ipld-dag-pb')

module.exports = (createCommon, options) => {
  const describe = getDescribe(options)
  const it = getIt(options)
  const common = createCommon()

  describe('.repo.gc', () => {
    let ipfs

    before(function (done) {
      // CI takes longer to instantiate the daemon, so we need to increase the
      // timeout for the before step
      this.timeout(60 * 1000)

      common.setup((err, factory) => {
        expect(err).to.not.exist()
        factory.spawnNode((err, node) => {
          expect(err).to.not.exist()
          ipfs = node
          done()
        })
      })
    })

    after((done) => common.teardown(done))

    it('should run garbage collection', (done) => {
      ipfs.repo.gc((err, res) => {
        expect(err).to.not.exist()
        expect(res).to.exist()
        done()
      })
    })

    it('should run garbage collection (promised)', () => {
      return ipfs.repo.gc().then((res) => {
        expect(res).to.exist()
      })
    })

    it('should clean up unpinned data', async () => {
      // Get initial list of local blocks
      const refsBeforeAdd = await ipfs.refs.local()

      // Add some data. Note: this will implicitly pin the data, which causes
      // some blocks to be added for the data itself and for the pinning
      // information that refers to the blocks
      const addRes = await ipfs.add(Buffer.from('apples'))
      const hash = addRes[0].hash

      // Get the list of local blocks after the add, should be bigger than
      // the initial list and contain hash
      const refsAfterAdd = await ipfs.refs.local()
      expect(refsAfterAdd.length).to.be.gt(refsBeforeAdd.length)
      expect(refsAfterAdd.map(r => r.ref)).includes(hash)

      // Run garbage collection
      await ipfs.repo.gc()

      // Get the list of local blocks after GC, should still contain the hash,
      // because the file is still pinned
      const refsAfterGc = await ipfs.refs.local()
      expect(refsAfterGc.map(r => r.ref)).includes(hash)

      // Unpin the data
      await ipfs.pin.rm(hash)

      // Run garbage collection
      await ipfs.repo.gc()

      // The list of local blocks should no longer contain the hash
      const refsAfterUnpinAndGc = await ipfs.refs.local()
      expect(refsAfterUnpinAndGc.map(r => r.ref)).not.includes(hash)
    })

    it('should clean up removed MFS files', async () => {
      // Get initial list of local blocks
      const refsBeforeAdd = await ipfs.refs.local()

      // Add a file to MFS
      await ipfs.files.write('/test', Buffer.from('oranges'), { create: true })
      const stats = await ipfs.files.stat('/test')
      expect(stats.type).to.equal('file')
      const hash = stats.hash

      // Get the list of local blocks after the add, should be bigger than
      // the initial list and contain hash
      const refsAfterAdd = await ipfs.refs.local()
      expect(refsAfterAdd.length).to.be.gt(refsBeforeAdd.length)
      expect(refsAfterAdd.map(r => r.ref)).includes(hash)

      // Run garbage collection
      await ipfs.repo.gc()

      // Get the list of local blocks after GC, should still contain the hash,
      // because the file is in MFS
      const refsAfterGc = await ipfs.refs.local()
      expect(refsAfterGc.map(r => r.ref)).includes(hash)

      // Remove the file
      await ipfs.files.rm('/test')

      // Run garbage collection
      await ipfs.repo.gc()

      // The list of local blocks should no longer contain the hash
      const refsAfterUnpinAndGc = await ipfs.refs.local()
      expect(refsAfterUnpinAndGc.map(r => r.ref)).not.includes(hash)
    })

    it('should clean up block only after unpinned and removed from MFS', async () => {
      // Get initial list of local blocks
      const refsBeforeAdd = await ipfs.refs.local()

      // Add a file to MFS
      await ipfs.files.write('/test', Buffer.from('peaches'), { create: true })
      const stats = await ipfs.files.stat('/test')
      expect(stats.type).to.equal('file')
      const mfsFileHash = stats.hash

      // Get the CID of the data in the file
      const block = await ipfs.block.get(mfsFileHash)

      // Add the data to IPFS (which implicitly pins the data)
      const addRes = await ipfs.add(block.data)
      const dataHash = addRes[0].hash

      // Get the list of local blocks after the add, should be bigger than
      // the initial list and contain the data hash
      const refsAfterAdd = await ipfs.refs.local()
      expect(refsAfterAdd.length).to.be.gt(refsBeforeAdd.length)
      const hashesAfterAdd = refsAfterAdd.map(r => r.ref)
      expect(hashesAfterAdd).includes(dataHash)

      // Run garbage collection
      await ipfs.repo.gc()

      // Get the list of local blocks after GC, should still contain the hash,
      // because the file is pinned and in MFS
      const refsAfterGc = await ipfs.refs.local()
      const hashesAfterGc = refsAfterGc.map(r => r.ref)
      expect(hashesAfterGc).includes(dataHash)

      // Remove the file
      await ipfs.files.rm('/test')

      // Run garbage collection
      await ipfs.repo.gc()

      // Get the list of local blocks after GC, should still contain the hash,
      // because the file is still pinned
      const refsAfterRmAndGc = await ipfs.refs.local()
      const hashesAfterRmAndGc = refsAfterRmAndGc.map(r => r.ref)
      expect(hashesAfterRmAndGc).not.includes(mfsFileHash)
      expect(hashesAfterRmAndGc).includes(dataHash)

      // Unpin the data
      await ipfs.pin.rm(dataHash)

      // Run garbage collection
      await ipfs.repo.gc()

      // The list of local blocks should no longer contain the hashes
      const refsAfterUnpinAndGc = await ipfs.refs.local()
      const hashesAfterUnpinAndGc = refsAfterUnpinAndGc.map(r => r.ref)
      expect(hashesAfterUnpinAndGc).not.includes(mfsFileHash)
      expect(hashesAfterUnpinAndGc).not.includes(dataHash)
    })

    it('should clean up indirectly pinned data after recursive pin removal', async () => {
      // Get initial list of local blocks
      const refsBeforeAdd = await ipfs.refs.local()

      // Add some data
      const addRes = await ipfs.add(Buffer.from('pears'))
      const dataHash = addRes[0].hash

      // Unpin the data
      await ipfs.pin.rm(dataHash)

      // Create a link to the data from an object
      const obj = await DAGNode.create(Buffer.from('fruit'), [{
        Name: 'p',
        Hash: dataHash,
        TSize: addRes[0].size
      }])

      // Put the object into IPFS
      const objHash = (await ipfs.object.put(obj)).toString()

      // Putting an object doesn't pin it
      expect((await ipfs.pin.ls()).map(p => p.hash)).not.includes(objHash)

      // Get the list of local blocks after the add, should be bigger than
      // the initial list and contain data and object hash
      const refsAfterAdd = await ipfs.refs.local()
      expect(refsAfterAdd.length).to.be.gt(refsBeforeAdd.length)
      const hashesAfterAdd = refsAfterAdd.map(r => r.ref)
      expect(hashesAfterAdd).includes(objHash)
      expect(hashesAfterAdd).includes(dataHash)

      // Recursively pin the object
      await ipfs.pin.add(objHash, { recursive: true })

      // The data should now be indirectly pinned
      const pins = await ipfs.pin.ls()
      expect(pins.find(p => p.hash === dataHash).type).to.eql('indirect')

      // Run garbage collection
      await ipfs.repo.gc()

      // Get the list of local blocks after GC, should still contain the data
      // hash, because the data is still (indirectly) pinned
      const refsAfterGc = await ipfs.refs.local()
      expect(refsAfterGc.map(r => r.ref)).includes(dataHash)

      // Recursively unpin the object
      await ipfs.pin.rm(objHash)

      // Run garbage collection
      await ipfs.repo.gc()

      // The list of local blocks should no longer contain the hashes
      const refsAfterUnpinAndGc = await ipfs.refs.local()
      const hashesAfterUnpinAndGc = refsAfterUnpinAndGc.map(r => r.ref)
      expect(hashesAfterUnpinAndGc).not.includes(objHash)
      expect(hashesAfterUnpinAndGc).not.includes(dataHash)
    })
  })
}

{'fraction_non_alphanumeric': 0.11841685285668688, 'fraction_numerical': 0.002021491648047665, 'mean_word_length': 2.4905310063126627, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5473162', 'n_tokens_mistral': 2935, 'n_tokens_neox': 2836, 'n_words': 814}