Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@
"gzip-js": "^0.3.2",
"html-entities": "^2.3.2",
"html-react-parser": "^1.2.4",
"java-object-serialization": "^0.1.1",
"java-object-serialization": "^0.1.2",
"js-yaml": "^4.1.0",
"json-bigint": "^1.0.0",
"jsonpath": "^1.1.1",
Expand Down
7 changes: 7 additions & 0 deletions redisinsight/ui/src/utils/formatters/bufferFormatters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ObjectInputStream } from 'java-object-serialization'
import { TextDecoder, TextEncoder } from 'text-encoding'
import { Buffer } from 'buffer'
import { KeyValueFormat } from 'uiSrc/constants'
import JavaDate from './java-date'
// eslint-disable-next-line import/order
import {
RedisResponseBuffer,
Expand All @@ -12,6 +13,8 @@ import {
} from 'uiSrc/slices/interfaces'
import { Nullable } from '../types'

ObjectInputStream.RegisterObjectClass(JavaDate, JavaDate.ClassName, JavaDate.SerialVersionUID)

const decoder = new TextDecoder('utf-8')
const encoder = new TextEncoder()

Expand Down Expand Up @@ -171,6 +174,10 @@ const bufferToJava = (reply: RedisResponseBuffer) => {
return decoded
}

if (decoded instanceof Date) {
return decoded
}

const { fields } = decoded
const fieldsArray = Array.from(fields, ([key, value]) => ({ [key]: value }))
return { ...decoded, fields: fieldsArray }
Expand Down
42 changes: 42 additions & 0 deletions redisinsight/ui/src/utils/formatters/java-date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ObjectInputStream, JavaSerializable } from 'java-object-serialization'

export default class JavaDate implements JavaSerializable {
// The class name in the serialized data
static readonly ClassName = 'java.util.Date'

// The serial version UID followed for 'java.util.Date'
static readonly SerialVersionUID = '7523967970034938905'

// The maximum value for a Java long
readonly JAVA_MAX_LONG = 9223372036854775807n // 2^63 - 1

// The maximum value for a two's complement long
readonly TWO_COMPLEMENT_MAX_LONG = 18446744073709551616n // 2^64

time: bigint = 0n

readObject(stream: ObjectInputStream): void {
this.time = stream.readLong()
}

readResolve() {
let timeValue: number

// Handle two's complement conversion for negative numbers
if (this.time > this.JAVA_MAX_LONG) {
// If the number is larger than MAX_LONG, it's a negative number in two's complement
timeValue = Number(this.time - this.TWO_COMPLEMENT_MAX_LONG)
} else {
timeValue = Number(this.time)
}

const date = new Date(timeValue)

// Validate the date
if (Number.isNaN(date.getTime())) {
throw new Error(`Invalid date value: ${timeValue} (original: ${this.time})`)
}

return date
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { input } from '@testing-library/user-event/dist/types/event'
import { RedisResponseBufferType } from 'uiSrc/slices/interfaces'
import JavaDate from 'uiSrc/utils/formatters/java-date'
import {
bufferToString,
anyToBuffer,
Expand All @@ -16,6 +17,12 @@ import {
bufferToUint8Array,
} from 'uiSrc/utils'

try {
// Register JavaDate class for deserialization
ObjectInputStream.RegisterObjectClass(JavaDate, JavaDate.ClassName, JavaDate.SerialVersionUID)
// eslint-disable-next-line no-empty
} catch (e) {}

const defaultValues = [
{ unicode: 'test', ascii: 'test', hex: '74657374', uint8Array: [116, 101, 115, 116], binary: '01110100011001010111001101110100' },
{ unicode: 'test test', ascii: 'test test', hex: '746573742074657374', uint8Array: [116, 101, 115, 116, 32, 116, 101, 115, 116], binary: '011101000110010101110011011101000010000001110100011001010111001101110100' },
Expand Down Expand Up @@ -134,6 +141,7 @@ describe('binaryToBuffer', () => {
const javaValues = [
{ uint8Array: [172, 237, 0, 5, 115, 114, 0, 8, 69, 109, 112, 108, 111, 121, 101, 101, 2, 94, 116, 52, 103, 198, 18, 60, 2, 0, 3, 73, 0, 6, 110, 117, 109, 98, 101, 114, 76, 0, 7, 97, 100, 100, 114, 101, 115, 115, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 4, 110, 97, 109, 101, 113, 0, 126, 0, 1, 120, 112, 0, 0, 0, 101, 116, 0, 25, 80, 104, 111, 107, 107, 97, 32, 75, 117, 97, 110, 44, 32, 65, 109, 98, 101, 104, 116, 97, 32, 80, 101, 101, 114, 116, 0, 9, 82, 101, 121, 97, 110, 32, 65, 108, 105], value: { annotations: [], className: 'Employee', fields: [{ number: 101 }, { address: 'Phokka Kuan, Ambehta Peer' }, { name: 'Reyan Ali' }], serialVersionUid: 170701604314812988n } },
{ uint8Array: [172, 237, 0, 5, 115, 114, 0, 32, 115, 101, 114, 105, 97, 108, 105, 122, 97, 116, 105, 111, 110, 68, 101, 109, 111, 46, 65, 110, 110, 111, 116, 97, 116, 105, 111, 110, 84, 101, 115, 116, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 1, 73, 0, 6, 110, 117, 109, 98, 101, 114, 120, 112, 0, 0, 0, 90], value: { annotations: [], className: 'serializationDemo.AnnotationTest', fields: [{ number: 90 }], serialVersionUid: 2n } },
{ uint8Array: [ 172, 237, 0, 5, 115, 114, 0, 14, 106, 97, 118, 97, 46, 117, 116, 105, 108, 46, 68, 97, 116, 101, 104, 106, 129, 1, 75, 89, 116, 25, 3, 0, 0, 120, 112, 119, 8, 0, 0, 1, 146, 226, 121, 165, 136, 120, ], value: new Date(Number(1730376476040n)) },
]

const getBufferToJavaTests = javaValues.map(({ uint8Array, value }) =>
Expand All @@ -150,3 +158,4 @@ describe('bufferToUint8Array', () => {
expect(bufferToUint8Array(anyToBuffer(uint8Array))).toEqual(new Uint8Array(uint8Array))
})
})

2 changes: 1 addition & 1 deletion tests/e2e/tests/web/regression/browser/add-keys.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ test('Verify that user can add json with BigInt', async t => {
await t.click(browserPage.addKeyButton);

await t.click(browserPage.editJsonObjectButton);
await t.expect(await browserPage.jsonValueInput.textContent).contains('result', 'edit value is empty');
await t.expect(await browserPage.jsonValueInput.textContent).contains('message', 'edit value is empty');
await t.click(browserPage.cancelEditButton);

await t.click(browserPage.expandJsonObject);
Expand Down
18 changes: 13 additions & 5 deletions tests/e2e/tests/web/regression/browser/formatters.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,14 @@ fixture `Formatters`
.beforeEach(async() => {
await databaseHelper.acceptLicenseTermsAndAddDatabaseApi(ossStandaloneV8Config);

await populateHashWithFields(ossStandaloneV8Config.host, ossStandaloneV8Config.port, keyToAddParameters);
})
.afterEach(async() => {
// Clear keys and database
await apiKeyRequests.deleteKeyByNameApi(keyName, ossStandaloneV8Config.databaseName);
await databaseAPIRequests.deleteStandaloneDatabaseApi(ossStandaloneV8Config);
});

test.before(async t => {
await databaseHelper.acceptLicenseTermsAndAddDatabaseApi(ossStandaloneV8Config);

})('Verify that UTF8 in PHP serialized', async t => {
test('Verify that UTF8 in PHP serialized', async t => {
const phpValueChinese = '测试';
const phpValueCRussian = 'Привет мир!';
const setValue =`SET ${keyName} "a:3:{s:4:\\"name\\";s:6:\\"${phpValueChinese}\\";s:3:\\"age\\";i:30;s:7:\\"message\\";s:20:\\"${phpValueCRussian}\\";}"\n`;
Expand All @@ -51,3 +47,15 @@ test.before(async t => {
await t.expect(await browserPage.getStringKeyValue()).contains(phpValueChinese, 'data is not serialized in php');
await t.expect(await browserPage.getStringKeyValue()).contains(phpValueCRussian, 'data is not serialized in php');
});

test('Verify that dataTime is displayed in Java serialized', async t => {
const hexValue ='ACED00057372000E6A6176612E7574696C2E44617465686A81014B59741903000078707708000000BEACD0567278';
const javaTimeValue = '"1995-12-14T12:12:01.010Z"'

await browserPage.addHashKey(keyName);
// Add valid value in HEX format for convertion
await browserPage.selectFormatter('HEX');
await browserPage.editHashKeyValue(hexValue);
await browserPage.selectFormatter('Java serialized');
await t.expect(browserPage.hashFieldValue.innerText).eql(javaTimeValue, 'data is not serialized in java');
});
49 changes: 12 additions & 37 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8252,12 +8252,12 @@ jake@^10.8.5:
filelist "^1.0.1"
minimatch "^3.0.4"

java-object-serialization@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/java-object-serialization/-/java-object-serialization-0.1.1.tgz#b20f34a619df3ce4b58980d7d9893048a696a0bd"
integrity sha512-m1bd/kPwNjbrMrIITzMGWoXiSU5fzUg6IdzGDrmGNPahNQ5YVzY9dv5qQzAcRC7oy0C0CwDseatdeI6SKO8MLA==
java-object-serialization@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/java-object-serialization/-/java-object-serialization-0.1.2.tgz#229ee4b70ea89e72206e32a826afacd09d9badfd"
integrity sha512-l0V2a/E7r6ScqG+ne09KR7G1npbiVdDf3Vdk6fcn8jy5TQiTTOQbDg9OfBriv2NmnCxcm4NmFW2dAD9QaN/htw==
dependencies:
tslib "^2.1.0"
tslib "^2.8.0"

jest-changed-files@^29.7.0:
version "29.7.0"
Expand Down Expand Up @@ -12563,16 +12563,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"

"string-width-cjs@npm:string-width@^4.2.0":
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
Expand Down Expand Up @@ -12677,14 +12668,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand Down Expand Up @@ -13157,10 +13141,10 @@ tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==

tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf"
integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==
tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.1, tslib@^2.8.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==

tsutils@^3.21.0:
version "3.21.0"
Expand Down Expand Up @@ -14022,7 +14006,7 @@ word-wrap@1.2.4, word-wrap@^1.2.3, word-wrap@~1.2.3:
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand All @@ -14040,15 +14024,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
Expand Down
Loading