SRC_DIR = '../../src/log/'

fs = require 'fs'
utils = require '../TestUtils.coffee'
Addr64 = (require SRC_DIR + 'Addr64.coffee').Addr64
LogUtil = (require SRC_DIR + 'LogUtil.coffee').LogUtil
LogCache = (require SRC_DIR + 'LogCache.coffee').LogCache

cacheForSmallFiles = new Object()
cacheForBigFiles = new Object()

exports.smallFilesGroup = {
  setUp: (callback) ->
    path = utils.getNewDirName()
    cacheForSmallFiles = LogCache.create$String$int$int$int path, 1024, 16, 100
    try
      fs.mkdirSync path, '0777'
    catch e
    b = new Buffer 1024
    b.fill 0
    b.write "My first test file string for testing how cache reads files"
    f = "00000000000"
    fd = fs.openSync path + f + LogUtil.LOG_FILE_EXTENSION, 'w'
    fs.writeSync fd, b, 0, b.length, 0
    fs.closeSync fd
    b = new Buffer 1024
    b.fill 0
    b.write "Another test file string again for testing how cache reads files"
    f = "00000000001"
    fd = fs.openSync path + f + LogUtil.LOG_FILE_EXTENSION, 'w'
    fs.writeSync fd, b, 0, b.length, 0
    fs.closeSync fd
    callback()

  testingCache: (test) ->
    test.expect 40
    map = new Array()
    map[0] = "My first test fi"
    map[1] = "le string for te"
    map[2] = "sting how cache "
    map[3] = "reads files\0\0\0\0\0"
    map[4] = "Another test fil"
    map[5] = "e string again f"
    map[6] = "or testing how c"
    map[7] = "ache reads files"
    onGetPage = (buffer, addrStr) =>
      addr = Addr64.stringToAddr64$String$int addrStr, LogUtil.LOG_NAME_BASE
      for i in [0..3]
        if addr.toFloat() == i * 16
          n += 1
          test.equal buffer.toString(), map[i]
          test.equal cacheForSmallFiles.pages.get(Addr64.addr64ToString$Addr64$int(addr, LogUtil.LOG_NAME_BASE)).toString(), map[i]
          test.equal cacheForSmallFiles.getPage$Addr64$emit(addr.plus$int(2)).toString(), map[i]
          test.ok cacheForSmallFiles.pageAddr.equals$Addr64 addr
      for i in [4..7]
        if addr.toFloat() == 1024 + i * 16 - 64
          n += 1
          test.equal buffer.toString(), map[i]
          test.equal cacheForSmallFiles.pages.get(Addr64.addr64ToString$Addr64$int(addr, LogUtil.LOG_NAME_BASE)).toString(), map[i]
          test.equal cacheForSmallFiles.getPage$Addr64$emit(addr.plus$int(2)).toString(), map[i]
          test.ok cacheForSmallFiles.pageAddr.equals$Addr64 addr
      if n == 8
        test.done()
    n = 0
    for i in [0..3]
      addr = Addr64.create$int$int 0, i * 16 + 5
      addrStr = Addr64.addr64ToString$Addr64$int(addr.plus$int(-5), LogUtil.LOG_NAME_BASE)
      cacheForSmallFiles.once 'getPage' + addrStr, (buffer, addrString) =>
        onGetPage buffer, addrString
      test.equal cacheForSmallFiles.getPage$Addr64$emit(addr), undefined
    for i in [0..3]
      addr = Addr64.create$int$int 0, 1024 + i * 16 + 5
      addrStr = Addr64.addr64ToString$Addr64$int(addr.plus$int(-5), LogUtil.LOG_NAME_BASE)
      cacheForSmallFiles.once 'getPage' + addrStr, (buffer, addrString) =>
        onGetPage buffer, addrString
      test.equal cacheForSmallFiles.getPage$Addr64$emit(addr), undefined
}

exports.bigFilesGroup = {
  setUp: (callback) ->
    path = utils.getNewDirName()
    cacheForBigFiles = LogCache.create$String$int$int$int path, 1024 * 1024,
            1024 * 64, 100
    try
      fs.mkdirSync path, '0777'
    catch e
    b = new Buffer 1024 * 1024
    b.fill 'a'
    f = "00000000000"
    fd = fs.openSync(path + f + LogUtil.LOG_FILE_EXTENSION, 'w')
    fs.writeSync fd, b, 0, b.length, 0
    fs.closeSync fd
    callback()

  testingCache: (test) ->
    test.expect 4 * 4 #4 * 16
    b = new Buffer 1024 * 64
    b.fill 'a'
    onGetPage = (buffer, addrStr) =>
      addr = Addr64.stringToAddr64$String$int addrStr, LogUtil.LOG_NAME_BASE
      n += 1
      test.equal buffer.toString(), b.toString()
      test.equal cacheForBigFiles.getPage$Addr64$emit(addr.plus$int(17)).toString(), b.toString()
      test.ok cacheForBigFiles.pageAddr.equals$Addr64 addr
      if n == 4 #16
        test.done()
    n = 0
    for i in [0..3] #15]
      addr = Addr64.create$int$int 0, i * 1024 * 64 + 155
      addrStr = Addr64.addr64ToString$Addr64$int(addr.plus$int(-155), LogUtil.LOG_NAME_BASE)
      cacheForBigFiles.once 'getPage' + addrStr, (buffer, addrString) =>
        onGetPage buffer, addrString
      test.equal cacheForBigFiles.getPage$Addr64$emit(addr), undefined
}