text: import * as msgpackr from '../index.js'
  import chai from 'chai'
  //import inspector  from 'inspector'; inspector.open(9330, null, true); debugger
  import sampleData from './example4.json'
  function tryRequire(module) {
  	try {
  		return require(module)
  	} catch(error) {
  		return {}
  	}
  }
  //if (typeof chai === 'undefined') { chai = require('chai') }
  var assert = chai.assert
  //if (typeof msgpackr === 'undefined') { msgpackr = require('..') }
  var Packr = msgpackr.Packr
  var unpack = msgpackr.unpack
  var unpackMultiple = msgpackr.unpackMultiple
  var roundFloat32 = msgpackr.roundFloat32
  var pack = msgpackr.pack
  var DECIMAL_FIT = msgpackr.FLOAT32_OPTIONS.DECIMAL_FIT
  
  var addExtension = msgpackr.addExtension
  var zlib = tryRequire('zlib')
  var deflateSync = zlib.deflateSync
  var inflateSync = zlib.inflateSync
  var deflateSync = zlib.brotliCompressSync
  var inflateSync = zlib.brotliDecompressSync
  var constants = zlib.constants
  try {
  //	var { decode, encode } = require('msgpack-lite')
  } catch (error) {}
  
  var ITERATIONS = 4000
  
  suite('msgpackr basic tests', function(){
  	test('pack/unpack data', function(){
  		var data = {
  			data: [
  				{ a: 1, name: 'one', type: 'odd', isOdd: true },
  				{ a: 2, name: 'two', type: 'even'},
  				{ a: 3, name: 'three', type: 'odd', isOdd: true },
  				{ a: 4, name: 'four', type: 'even'},
  				{ a: 5, name: 'five', type: 'odd', isOdd: true },
  				{ a: 6, name: 'six', type: 'even', isOdd: null }
  			],
  			description: 'some names',
  			types: ['odd', 'even'],
  			convertEnumToNum: [
  				{ prop: 'test' },
  				{ prop: 'test' },
  				{ prop: 'test' },
  				{ prop: 1 },
  				{ prop: 2 },
  				{ prop: [undefined] },
  				{ prop: null }
  			]
  		}
  		let structures = []
  		let packr = new Packr({ structures })
  		var serialized = packr.pack(data)
  		var deserialized = packr.unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('mixed array', function(){
  		var data = [
  			'one',
  			'two',
  			'one',
  			10,
  			11,
  			null,
  			true,
  			'three',
  			'three',
  			'one', [
  				3, -5, -50, -400,1.3, -5.3, true
  			]
  		]
  		let structures = []
  		let packr = new Packr({ structures })
  		var serialized = packr.pack(data)
  		var deserialized = packr.unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('255 chars', function() {
  		const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W'
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.equal(deserialized, data)
  	})
  
  	test('pack/unpack sample data', function(){
  		var data = sampleData
  		let structures = []
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  	test('pack/unpack sample data with records', function(){
  		var data = sampleData
  		let structures = []
  		let packr = new Packr({ structures, useRecords: true })
  		var serialized = packr.pack(data)
  		var deserialized = packr.unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  	if (typeof Buffer != 'undefined')
  	test('replace data', function(){
  		var data1 = {
  			data: [
  				{ a: 1, name: 'one', type: 'odd', isOdd: true, a: '13 characters' },
  				{ a: 2, name: 'two', type: 'even', a: '11 characte' },
  				{ a: 3, name: 'three', type: 'odd', isOdd: true, a: '12 character' },
  				{ a: 4, name: 'four', type: 'even', a: '9 charact'},
  				{ a: 5, name: 'five', type: 'odd', isOdd: true, a: '14 characters!' },
  				{ a: 6, name: 'six', type: 'even', isOdd: null }
  			],
  		}
  		var data2 = {
  			data: [
  				{ foo: 7, name: 'one', type: 'odd', isOdd: true },
  				{ foo: 8, name: 'two', type: 'even'},
  				{ foo: 9, name: 'three', type: 'odd', isOdd: true },
  				{ foo: 10, name: 'four', type: 'even'},
  				{ foo: 11, name: 'five', type: 'odd', isOdd: true },
  				{ foo: 12, name: 'six', type: 'even', isOdd: null }
  			],
  		}
  		var serialized1 = pack(data1)
  		var serialized2 = pack(data2)
  		var b = Buffer.alloc(8000)
  		serialized1.copy(b)
  		var deserialized1 = unpack(b, serialized1.length)
  		serialized2.copy(b)
  		var deserialized2 = unpack(b, serialized2.length)
  		assert.deepEqual(deserialized1, data1)
  		assert.deepEqual(deserialized2, data2)
  	})
  
  	test('extended class pack/unpack', function(){
  		function Extended() {
  
  		}
  		Extended.prototype.getDouble = function() {
  			return this.value * 2
  		}
  		var instance = new Extended()
  		instance.value = 4
  		instance.string = 'decode this: ᾜ'
  		var data = {
  			prop1: 'has multi-byte: ᾜ',
  			extendedInstance: instance,
  			prop2: 'more string',
  			num: 3,
  		}
  		let packr = new Packr()
  		addExtension({
  			Class: Extended,
  			type: 11,
  			unpack: function(buffer) {
  				let e = new Extended()
  				let data = packr.unpack(buffer)
  				e.value = data[0]
  				e.string = data[1]
  				return e
  			},
  			pack: function(instance) {
  				return packr.pack([instance.value, instance.string])
  			}
  		})
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(data, deserialized)
  		assert.equal(deserialized.extendedInstance.getDouble(), 8)
  	})
  	test('extended class pack/unpack custom size', function(){
  		function TestClass() {
  
  		}
  		addExtension({
  			Class: TestClass,
  			type: 0x01,
  			pack() {
  				return typeof Buffer != 'undefined' ? Buffer.alloc(256) : new Uint8Array(256)
  			},
  			unpack(data) {
  				return data.length
  			}
  		});
  		let result = unpack(pack(new TestClass()));
  		assert.equal(result, 256)
  	})
  
  	test('extended class read/write', function(){
  		function Extended() {
  
  		}
  		Extended.prototype.getDouble = function() {
  			return this.value * 2
  		}
  		var instance = new Extended()
  		instance.value = 4
  		instance.string = 'decode this: ᾜ'
  		var data = {
  			prop1: 'has multi-byte: ᾜ',
  			extendedInstance: instance,
  			prop2: 'more string',
  			num: 3,
  		}
  		let packr = new Packr()
  		addExtension({
  			Class: Extended,
  			type: 12,
  			read: function(data) {
  				let e = new Extended()
  				e.value = data[0]
  				e.string = data[1]
  				return e
  			},
  			write: function(instance) {
  				return [instance.value, instance.string]
  			}
  		})
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(data, deserialized)
  		assert.equal(deserialized.extendedInstance.getDouble(), 8)
  	})
  
  	test.skip('text decoder', function() {
  			let td = new TextDecoder('ISO-8859-15')
  			let b = Buffer.alloc(3)
  			let total = 0
  			for (var i = 0; i < 256; i++) {
  				b[0] = i
  				b[1] = 0
  				b[2] = 0
  				let s = td.decode(b)
  				if (!require('msgpackr-extract').isOneByte(s)) {
  					console.log(i.toString(16), s.length)
  					total++
  				}
  			}
  	})
  
  	test('structured cloning: self reference', function() {
  		let object = {
  			test: 'string',
  			children: [
  				{ name: 'child' }
  			]
  		}
  		object.self = object
  		object.children[1] = object
  		object.children[2] = object.children[0]
  		object.childrenAgain = object.children
  		let packr = new Packr({
  			structuredClone: true,
  		})
  		var serialized = packr.pack(object)
  		var deserialized = packr.unpack(serialized)
  		assert.equal(deserialized.self, deserialized)
  		assert.equal(deserialized.children[0].name, 'child')
  		assert.equal(deserialized.children[1], deserialized)
  		assert.equal(deserialized.children[0], deserialized.children[2])
  		assert.equal(deserialized.children, deserialized.childrenAgain)
  	})
  
  	test('structured cloning: types', function() {
  		let b = typeof Buffer != 'undefined' ? Buffer.alloc(20) : new Uint8Array(20)
  		let fa = new Float32Array(b.buffer, 8, 2)
  		fa[0] = 2.25
  		fa[1] = 6
  		let object = {
  			error: new Error('test'),
  			set: new Set(['a', 'b']),
  			regexp: /test/gi,
  			float32Array: fa,
  			uint16Array: new Uint16Array([3,4])
  		}
  		let packr = new Packr({
  			structuredClone: true,
  		})
  		var serialized = packr.pack(object)
  		var deserialized = packr.unpack(serialized)
  		assert.deepEqual(Array.from(deserialized.set), Array.from(object.set))
  		assert.equal(deserialized.error.message, object.error.message)
  		assert.equal(deserialized.regexp.test('TEST'), true)
  		assert.equal(deserialized.float32Array.constructor.name, 'Float32Array')
  		assert.equal(deserialized.float32Array[0], 2.25)
  		assert.equal(deserialized.float32Array[1], 6)
  		assert.equal(deserialized.uint16Array.constructor.name, 'Uint16Array')
  		assert.equal(deserialized.uint16Array[0], 3)
  		assert.equal(deserialized.uint16Array[1], 4)
  	})
  
  	test('object without prototype', function(){
  		var data = Object.create(null)
  		data.test = 3
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('many shared structures', function() {
  		let data = []
  		for (let i = 0; i < 200; i++) {
  			data.push({['a' + i]: i})
  		}
  		let structures = []
  		let savedStructures
  		let packr = new Packr({
  			structures,
  			saveStructures(structures) {
  				savedStructures = structures
  			}
  		})
  		var serializedWith32 = packr.pack(data)
  		assert.equal(savedStructures.length, 32)
  		var deserialized = packr.unpack(serializedWith32)
  		assert.deepEqual(deserialized, data)
  		structures = structures.slice(0, 32)
  		packr = new Packr({
  			structures,
  			maxSharedStructures: 100,
  			saveStructures(structures) {
  				savedStructures = structures
  			}
  		})
  		deserialized = packr.unpack(serializedWith32)
  		assert.deepEqual(deserialized, data)
  		structures = structures.slice(0, 32)
  		packr = new Packr({
  			structures,
  			maxSharedStructures: 100,
  			saveStructures(structures) {
  				savedStructures = structures
  			}
  		})
  		let serialized = packr.pack(data)
  		assert.equal(savedStructures.length, 100)
  		deserialized = packr.unpack(serialized)
  		assert.deepEqual(deserialized, data)
  
  		deserialized = packr.unpack(serializedWith32)
  		assert.deepEqual(deserialized, data)
  		assert.equal(savedStructures.length, 100)
  
  		deserialized = packr.unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		assert.equal(packr.structures.sharedLength, 100)
  	})
  	test('more shared structures', function() {
  		const structures = []
  		for (let i = 0; i < 40; i++) {
  			structures.push(['a' + i])
  		}
  		const structures2 = [...structures]
  		const packr = new Packr({
  			getStructures() {
  				return structures
  			},
  			saveStructures(structures) {		  
  			},
  			maxSharedStructures: 100
  		})
  		const packr2 = new Packr({
  			getStructures() {
  				return structures2
  			},
  			saveStructures(structures) {		  
  			},
  			maxSharedStructures: 100
  		})
  		const inputData = {a35: 35}
  		const buffer = packr.pack(inputData)
  		const outputData = packr2.decode(buffer)
  		assert.deepEqual(inputData, outputData)
  	})
  
  	test('big buffer', function() {
  		var size = 100000000
  		var data = new Uint8Array(size).fill(1)
  		var packed = pack(data)
  		var unpacked = unpack(packed)
  		assert.equal(unpacked.length, size)
  	})
  
  	test('random strings', function(){
  		var data = []
  		for (var i = 0; i < 2000; i++) {
  			var str = 'test'
  			while (Math.random() < 0.7 && str.length < 0x100000) {
  				str = str + String.fromCharCode(90/(Math.random() + 0.01)) + str
  			}
  			data.push(str)
  		}
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('map/date', function(){
  		var map = new Map()
  		map.set(4, 'four')
  		map.set('three', 3)
  
  
  		var data = {
  			map: map,
  			date: new Date(1532219539733),
  			farFutureDate: new Date(3532219539133),
  			ancient: new Date(-3532219539133),
  		}
  		let packr = new Packr()
  		var serialized = packr.pack(data)
  		var deserialized = packr.unpack(serialized)
  		assert.equal(deserialized.map.get(4), 'four')
  		assert.equal(deserialized.map.get('three'), 3)
  		assert.equal(deserialized.date.getTime(), 1532219539733)
  		assert.equal(deserialized.farFutureDate.getTime(), 3532219539133)
  		assert.equal(deserialized.ancient.getTime(), -3532219539133)
  	})
  	test('map/date with options', function(){
  		var map = new Map()
  		map.set(4, 'four')
  		map.set('three', 3)
  
  
  		var data = {
  			map: map,
  			date: new Date(1532219539011),
  		}
  		let packr = new Packr({
  			mapsAsObjects: true,
  			useTimestamp32: true,
  		})
  		var serialized = packr.pack(data)
  		var deserialized = packr.unpack(serialized)
  		assert.equal(deserialized.map[4], 'four')
  		assert.equal(deserialized.map.three, 3)
  		assert.equal(deserialized.date.getTime(), 1532219539000)
  	})
  	test('key caching', function() {
  		var data = {
  			foo: 2,
  			bar: 'test',
  			four: 4,
  			seven: 7,
  			foz: 3,
  		}
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		// do multiple times to test caching
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  	test('strings', function() {
  		var data = ['']
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		// do multiple times
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		data = 'decode this: ᾜ'
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		data = 'decode this that is longer but without any non-latin characters'
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  	test('decimal float32', function() {
  		var data = {
  			a: 2.526,
  			b: 0.0035235,
  			c: 0.00000000000352501,
  			d: 3252.77,
  		}
  		let packr = new Packr({
  			useFloat32: DECIMAL_FIT
  		})
  		var serialized = packr.pack(data)
  		assert.equal(serialized.length, 32)
  		var deserialized = packr.unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('numbers', function(){
  		var data = {
  			bigEncodable: 48978578104322,
  			dateEpoch: 1530886513200,
  			realBig: 3432235352353255323,
  			decimal: 32.55234,
  			negative: -34.11,
  			exponential: 0.234e123,
  			tiny: 3.233e-120,
  			zero: 0,
  			//negativeZero: -0,
  			Infinity: Infinity
  		}
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  	test('bigint', function(){
  		var data = {
  			bigintSmall: 352n,
  			bigintSmallNegative: -333335252n,
  			bigintBig: 2n**64n - 1n, // biggest possible
  			bigintBigNegative: -(2n**63n), // largest negative
  			mixedWithNormal: 44,
  		}
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  		var tooBigInt = {
  			tooBig: 2n**66n
  		}
  		assert.throws(function(){ serialized = pack(tooBigInt) })
  		let packr = new Packr({
  			largeBigIntToFloat: true
  		})
  		serialized = packr.pack(tooBigInt)
  		deserialized = unpack(serialized)
  		assert.isTrue(deserialized.tooBig > 2n**65n)
  	})
  
  	test('roundFloat32', function() {
  		assert.equal(roundFloat32(0.00333000003), 0.00333)
  		assert.equal(roundFloat32(43.29999999993), 43.3)
  	})
  
  	test('buffers', function(){
  		var data = {
  			buffer1: new Uint8Array([2,3,4]),
  			buffer2: new Uint8Array(pack(sampleData))
  		}
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('notepack test', function() {
  		const data = {
  		  foo: 1,
  		  bar: [1, 2, 3, 4, 'abc', 'def'],
  		  foobar: {
  		    foo: true,
  		    bar: -2147483649,
  		    foobar: {
  		      foo: new Uint8Array([1, 2, 3, 4, 5]),
  		      bar: 1.5,
  		      foobar: [true, false, 'abcdefghijkmonpqrstuvwxyz']
  		    }
  		  }
  		};
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		var deserialized = unpack(serialized)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  
  	test('utf16 causing expansion', function() {
  		this.timeout(10000)
  		let data = {fixstr: 'ᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝ', str8:'ᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝᾐᾑᾒᾓᾔᾕᾖᾗᾘᾙᾚᾛᾜᾝ'}
  		var serialized = pack(data)
  		var deserialized = unpack(serialized)
  		assert.deepEqual(deserialized, data)
  	})
  	test('unpackMultiple', () => {
  		let values = unpackMultiple(new Uint8Array([1, 2, 3, 4]))
  		assert.deepEqual(values, [1, 2, 3, 4])
  		values = []
  		unpackMultiple(new Uint8Array([1, 2, 3, 4]), value => values.push(value))
  		assert.deepEqual(values, [1, 2, 3, 4])
  	})
  
  })
  suite('msgpackr performance tests', function(){
  	test('performance JSON.parse', function() {
  		var data = sampleData
  		this.timeout(10000)
  		let structures = []
  		var serialized = JSON.stringify(data)
  		console.log('JSON size', serialized.length)
  		for (var i = 0; i < ITERATIONS; i++) {
  			var deserialized = JSON.parse(serialized)
  		}
  	})
  	test('performance JSON.stringify', function() {
  		var data = sampleData
  		this.timeout(10000)
  		for (var i = 0; i < ITERATIONS; i++) {
  			var serialized = JSON.stringify(data)
  		}
  	})
  	test('performance unpack', function() {
  		var data = sampleData
  		this.timeout(10000)
  		let structures = []
  		var serialized = pack(data)
  		console.log('MessagePack size', serialized.length)
  		let packr = new Packr({ structures })
  		var serialized = packr.pack(data)
  		console.log('msgpackr w/ record ext size', serialized.length)
  		for (var i = 0; i < ITERATIONS; i++) {
  			var deserialized = packr.unpack(serialized)
  		}
  	})
  	test('performance pack', function() {
  		var data = sampleData
  		this.timeout(10000)
  		let structures = []
  		let packr = new Packr({ structures })
  		let buffer = typeof Buffer != 'undefined' ? Buffer.alloc(0x10000) : new Uint8Array(0x10000)
  
  		for (var i = 0; i < ITERATIONS; i++) {
  			//serialized = pack(data, { shared: sharedStructure })
  			packr.useBuffer(buffer)
  			var serialized = packr.pack(data)
  			//var serializedGzip = deflateSync(serialized)
  		}
  		//console.log('serialized', serialized.length, global.propertyComparisons)
  	})
  })
  