heatmap_data_converter_specs.ts 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. ///<reference path="../../../../headers/common.d.ts" />
  2. import _ from 'lodash';
  3. import { describe, beforeEach, it, sinon, expect, angularMocks } from '../../../../../test/lib/common';
  4. import TimeSeries from 'app/core/time_series2';
  5. import { convertToHeatMap, elasticHistogramToHeatmap, calculateBucketSize, isHeatmapDataEqual } from '../heatmap_data_converter';
  6. describe('isHeatmapDataEqual', () => {
  7. let ctx: any = {};
  8. beforeEach(() => {
  9. ctx.heatmapA = {
  10. '1422774000000': {
  11. x: 1422774000000,
  12. buckets: {
  13. '1': { y: 1, values: [1, 1.5] },
  14. '2': { y: 2, values: [1] }
  15. }
  16. }
  17. };
  18. ctx.heatmapB = {
  19. '1422774000000': {
  20. x: 1422774000000,
  21. buckets: {
  22. '1': { y: 1, values: [1.5, 1] },
  23. '2': { y: 2, values: [1] }
  24. }
  25. }
  26. };
  27. });
  28. it('should proper compare objects', () => {
  29. let heatmapC = _.cloneDeep(ctx.heatmapA);
  30. heatmapC['1422774000000'].buckets['1'].values = [1, 1.5];
  31. let heatmapD = _.cloneDeep(ctx.heatmapA);
  32. heatmapD['1422774000000'].buckets['1'].values = [1.5, 1, 1.6];
  33. let heatmapE = _.cloneDeep(ctx.heatmapA);
  34. heatmapE['1422774000000'].buckets['1'].values = [1, 1.6];
  35. let empty = {};
  36. let emptyValues = _.cloneDeep(ctx.heatmapA);
  37. emptyValues['1422774000000'].buckets['1'].values = [];
  38. expect(isHeatmapDataEqual(ctx.heatmapA, ctx.heatmapB)).to.be(true);
  39. expect(isHeatmapDataEqual(ctx.heatmapB, ctx.heatmapA)).to.be(true);
  40. expect(isHeatmapDataEqual(ctx.heatmapA, heatmapC)).to.be(true);
  41. expect(isHeatmapDataEqual(heatmapC, ctx.heatmapA)).to.be(true);
  42. expect(isHeatmapDataEqual(ctx.heatmapA, heatmapD)).to.be(false);
  43. expect(isHeatmapDataEqual(heatmapD, ctx.heatmapA)).to.be(false);
  44. expect(isHeatmapDataEqual(ctx.heatmapA, heatmapE)).to.be(false);
  45. expect(isHeatmapDataEqual(heatmapE, ctx.heatmapA)).to.be(false);
  46. expect(isHeatmapDataEqual(empty, ctx.heatmapA)).to.be(false);
  47. expect(isHeatmapDataEqual(ctx.heatmapA, empty)).to.be(false);
  48. expect(isHeatmapDataEqual(emptyValues, ctx.heatmapA)).to.be(false);
  49. expect(isHeatmapDataEqual(ctx.heatmapA, emptyValues)).to.be(false);
  50. });
  51. });
  52. describe('calculateBucketSize', () => {
  53. let ctx: any = {};
  54. describe('when logBase is 1 (linear scale)', () => {
  55. beforeEach(() => {
  56. ctx.logBase = 1;
  57. ctx.bounds_set = [
  58. { bounds: [], size: 0 },
  59. { bounds: [0], size: 0 },
  60. { bounds: [4], size: 4 },
  61. { bounds: [0, 1, 2, 3, 4], size: 1 },
  62. { bounds: [0, 1, 3, 5, 7], size: 1 },
  63. { bounds: [0, 3, 7, 9, 15], size: 2 },
  64. { bounds: [0, 7, 3, 15, 9], size: 2 },
  65. { bounds: [0, 5, 10, 15, 50], size: 5 }
  66. ];
  67. });
  68. it('should properly calculate bucket size', () => {
  69. _.each(ctx.bounds_set, (b) => {
  70. let bucketSize = calculateBucketSize(b.bounds, ctx.logBase);
  71. expect(bucketSize).to.be(b.size);
  72. });
  73. });
  74. });
  75. describe('when logBase is 2', () => {
  76. beforeEach(() => {
  77. ctx.logBase = 2;
  78. ctx.bounds_set = [
  79. { bounds: [], size: 0 },
  80. { bounds: [0], size: 0 },
  81. { bounds: [4], size: 4 },
  82. { bounds: [1, 2, 4, 8], size: 1 },
  83. { bounds: [1, Math.SQRT2, 2, 8, 16], size: 0.5 }
  84. ];
  85. });
  86. it('should properly calculate bucket size', () => {
  87. _.each(ctx.bounds_set, (b) => {
  88. let bucketSize = calculateBucketSize(b.bounds, ctx.logBase);
  89. expect(isEqual(bucketSize, b.size)).to.be(true);
  90. });
  91. });
  92. });
  93. });
  94. describe('HeatmapDataConverter', () => {
  95. let ctx: any = {};
  96. beforeEach(() => {
  97. ctx.series = [];
  98. ctx.series.push(new TimeSeries({
  99. datapoints: [[1, 1422774000000], [2, 1422774060000]],
  100. alias: 'series1'
  101. }));
  102. ctx.series.push(new TimeSeries({
  103. datapoints: [[2, 1422774000000], [3, 1422774060000]],
  104. alias: 'series2'
  105. }));
  106. ctx.xBucketSize = 60000; // 60s
  107. ctx.yBucketSize = 1;
  108. ctx.logBase = 1;
  109. });
  110. describe('when logBase is 1 (linear scale)', () => {
  111. beforeEach(() => {
  112. ctx.logBase = 1;
  113. });
  114. it('should build proper heatmap data', () => {
  115. let expectedHeatmap = {
  116. '1422774000000': {
  117. x: 1422774000000,
  118. buckets: {
  119. '1': { y: 1, values: [1] },
  120. '2': { y: 2, values: [2] }
  121. }
  122. },
  123. '1422774060000': {
  124. x: 1422774060000,
  125. buckets: {
  126. '2': { y: 2, values: [2] },
  127. '3': { y: 3, values: [3] }
  128. }
  129. },
  130. };
  131. let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase);
  132. expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true);
  133. });
  134. });
  135. describe('when logBase is 2', () => {
  136. beforeEach(() => {
  137. ctx.logBase = 2;
  138. });
  139. it('should build proper heatmap data', () => {
  140. let expectedHeatmap = {
  141. '1422774000000': {
  142. x: 1422774000000,
  143. buckets: {
  144. '1': { y: 1, values: [1] },
  145. '2': { y: 2, values: [2] }
  146. }
  147. },
  148. '1422774060000': {
  149. x: 1422774060000,
  150. buckets: {
  151. '2': { y: 2, values: [2, 3] }
  152. }
  153. },
  154. };
  155. let heatmap = convertToHeatMap(ctx.series, ctx.yBucketSize, ctx.xBucketSize, ctx.logBase);
  156. expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true);
  157. });
  158. });
  159. });
  160. describe('ES Histogram converter', () => {
  161. let ctx: any = {};
  162. beforeEach(() => {
  163. ctx.series = [];
  164. ctx.series.push(new TimeSeries({
  165. datapoints: [[1, 1422774000000], [0, 1422774060000]],
  166. alias: '1', label: '1'
  167. }));
  168. ctx.series.push(new TimeSeries({
  169. datapoints: [[1, 1422774000000], [3, 1422774060000]],
  170. alias: '2', label: '2'
  171. }));
  172. ctx.series.push(new TimeSeries({
  173. datapoints: [[0, 1422774000000], [1, 1422774060000]],
  174. alias: '3', label: '3'
  175. }));
  176. });
  177. describe('when converting ES histogram', () => {
  178. beforeEach(() => {
  179. });
  180. it('should build proper heatmap data', () => {
  181. let expectedHeatmap = {
  182. '1422774000000': {
  183. x: 1422774000000,
  184. buckets: {
  185. '1': { y: 1, values: [1] },
  186. '2': { y: 2, values: [2] }
  187. }
  188. },
  189. '1422774060000': {
  190. x: 1422774060000,
  191. buckets: {
  192. '2': { y: 2, values: [2, 2, 2] },
  193. '3': { y: 3, values: [3] }
  194. }
  195. },
  196. };
  197. let heatmap = elasticHistogramToHeatmap(ctx.series);
  198. expect(isHeatmapDataEqual(heatmap, expectedHeatmap)).to.be(true);
  199. });
  200. });
  201. });
  202. /**
  203. * Compare two numbers with given precision. Suitable for compare float numbers after conversions with precision loss.
  204. * @param a
  205. * @param b
  206. * @param precision
  207. */
  208. function isEqual(a: number, b: number, precision = 0.000001): boolean {
  209. if (a === b) {
  210. return true;
  211. } else {
  212. return Math.abs(1 - a / b) <= precision;
  213. }
  214. }