1 import { IntegrityMetrics, getAddressMatchingDefaultShare, getFileSize, getFromBefore2024 } from './integrityMetrics';
3 class IntegrityMetricsForTesting extends IntegrityMetrics {
4 setMetricsModule(metricsModule: any) {
5 this.metricsModule = metricsModule;
9 return this.reportedShareIds;
13 return this.reportedNodeIds;
17 describe('IntegrityMetrics::', () => {
18 const mockMetricsDecryptionErrors = jest.fn();
19 const mockMetricsVerificationErrors = jest.fn();
20 const mockMetricsBlockVerificationErrors = jest.fn();
21 const mockMetricsErroringUsers = jest.fn();
23 let integrityMetrics: IntegrityMetricsForTesting;
27 integrityMetrics = new IntegrityMetricsForTesting();
28 integrityMetrics.setMetricsModule({
29 drive_integrity_decryption_errors_total: { increment: mockMetricsDecryptionErrors },
30 drive_integrity_verification_errors_total: { increment: mockMetricsVerificationErrors },
31 drive_integrity_block_verification_errors_total: { increment: mockMetricsBlockVerificationErrors },
32 drive_integrity_erroring_users_total: { increment: mockMetricsErroringUsers },
36 describe('shareDecryptionError', () => {
37 it('reports each share only once', () => {
38 integrityMetrics.shareDecryptionError('shareId1', 'main', { isPaid: false, createTime: 0 });
39 integrityMetrics.shareDecryptionError('shareId1', 'main', { isPaid: false, createTime: 0 });
40 integrityMetrics.shareDecryptionError('shareId2', 'device', { isPaid: false, createTime: 0 });
41 expect(mockMetricsDecryptionErrors).toHaveBeenCalledTimes(2);
42 expect(mockMetricsDecryptionErrors).toHaveBeenCalledWith({
45 fromBefore2024: 'unknown',
47 expect(mockMetricsDecryptionErrors).toHaveBeenCalledWith({
50 fromBefore2024: 'unknown',
54 it('does not call affected user if year is before 2024', () => {
55 integrityMetrics.shareDecryptionError('shareId1', 'main', { isPaid: false, createTime: 1704060000 });
56 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(0);
59 it('calls also affected user if year is 2024 or newer', () => {
60 integrityMetrics.shareDecryptionError('shareId1', 'main', { isPaid: false, createTime: 1725544806 });
61 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(1);
65 describe('nodeDecryptionError', () => {
66 it('reports each node only once', () => {
67 integrityMetrics.nodeDecryptionError('nodeId1', 'main', { isPaid: false, createTime: 0 });
68 integrityMetrics.nodeDecryptionError('nodeId1', 'main', { isPaid: false, createTime: 0 });
69 integrityMetrics.nodeDecryptionError('nodeId2', 'device', { isPaid: false, createTime: 0 });
70 expect(mockMetricsDecryptionErrors).toHaveBeenCalledTimes(2);
71 expect(mockMetricsDecryptionErrors).toHaveBeenCalledWith({
74 fromBefore2024: 'unknown',
76 expect(mockMetricsDecryptionErrors).toHaveBeenCalledWith({
79 fromBefore2024: 'unknown',
83 it('does not call affected user if year is before 2024', () => {
84 integrityMetrics.nodeDecryptionError('nodeId1', 'main', { isPaid: false, createTime: 1704060000 });
85 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(0);
88 it('calls also affected user if year is 2024 or newer', () => {
89 integrityMetrics.nodeDecryptionError('nodeId1', 'main', { isPaid: false, createTime: 1725544806 });
90 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(1);
94 describe('signatureVerificationError', () => {
95 it('reports each node only once', () => {
96 integrityMetrics.signatureVerificationError('nodeId1', 'main', 'NodeKey', {
99 addressMatchingDefaultShare: undefined,
101 integrityMetrics.signatureVerificationError('nodeId1', 'main', 'NodeKey', {
104 addressMatchingDefaultShare: undefined,
106 integrityMetrics.signatureVerificationError('nodeId2', 'device', 'SignatureEmail', {
109 addressMatchingDefaultShare: undefined,
111 expect(mockMetricsVerificationErrors).toHaveBeenCalledTimes(2);
112 expect(mockMetricsVerificationErrors).toHaveBeenCalledWith({
114 verificationKey: 'NodeKey',
115 fromBefore2024: 'unknown',
116 addressMatchingDefaultShare: 'unknown',
118 expect(mockMetricsVerificationErrors).toHaveBeenCalledWith({
120 verificationKey: 'SignatureEmail',
121 fromBefore2024: 'unknown',
122 addressMatchingDefaultShare: 'unknown',
126 it('does not call affected user if year is before 2024 or doesnt have matching address with default share', () => {
127 integrityMetrics.signatureVerificationError('nodeId1', 'main', 'NodeKey', {
129 createTime: 1704060000,
130 addressMatchingDefaultShare: false,
132 integrityMetrics.signatureVerificationError('nodeId2', 'main', 'NodeKey', {
134 createTime: 1704060000,
135 addressMatchingDefaultShare: true,
137 integrityMetrics.signatureVerificationError('nodeId3', 'main', 'NodeKey', {
139 createTime: 1725544806,
140 addressMatchingDefaultShare: false,
142 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(0);
145 it('calls also affected user if year is 2024 or newer', () => {
146 integrityMetrics.signatureVerificationError('nodeId1', 'main', 'NodeKey', {
148 createTime: 1725544806,
149 addressMatchingDefaultShare: true,
151 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(1);
155 describe('nodeBlockVerificationError', () => {
156 it('reports each incident', () => {
157 integrityMetrics.nodeBlockVerificationError('main', 1234, { isPaid: false, retryHelped: true });
158 integrityMetrics.nodeBlockVerificationError('device', 1234, { isPaid: false, retryHelped: true });
159 expect(mockMetricsBlockVerificationErrors).toHaveBeenCalledTimes(2);
160 expect(mockMetricsBlockVerificationErrors).toHaveBeenCalledWith({
165 expect(mockMetricsBlockVerificationErrors).toHaveBeenCalledWith({
172 it('does not call affected user if retry helped', () => {
173 integrityMetrics.nodeBlockVerificationError('main', 1234, { isPaid: false, retryHelped: true });
174 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(0);
177 it('calls also affected user if retry didnt help', () => {
178 integrityMetrics.nodeBlockVerificationError('main', 1234, { isPaid: false, retryHelped: false });
179 expect(mockMetricsErroringUsers).toHaveBeenCalledTimes(1);
184 describe('getFromBefore2024', () => {
185 it('returns unknwon for empty time', () => {
186 expect(getFromBefore2024(undefined)).toBe('unknown');
187 expect(getFromBefore2024(0)).toBe('unknown');
190 it('returns yes for anythign before 2024', () => {
191 expect(getFromBefore2024(1)).toBe('yes');
192 expect(getFromBefore2024(1111111)).toBe('yes');
193 expect(getFromBefore2024(1704060000)).toBe('yes'); // Dec 31, 2023
196 it('returns no for 2024 and later', () => {
197 expect(getFromBefore2024(1704067200)).toBe('no'); // Jan 1, 2024
198 expect(getFromBefore2024(1710000000)).toBe('no');
202 describe('getAddressMatchingDefaultShare', () => {
203 it('returns unknwon for undefined', () => {
204 expect(getAddressMatchingDefaultShare(undefined)).toBe('unknown');
207 it('returns yes or no based on boolean value', () => {
208 expect(getAddressMatchingDefaultShare(true)).toBe('yes');
209 expect(getAddressMatchingDefaultShare(false)).toBe('no');
213 describe('getFileSize', () => {
214 it('returns proper matching size bucket', () => {
215 expect(getFileSize(0)).toBe('2**10');
216 expect(getFileSize(1234)).toBe('2**20');
217 expect(getFileSize(123456)).toBe('2**20');