mirror of
https://github.com/mudita/mudita-center.git
synced 2025-12-23 22:28:03 -05:00
[CP-3547] Script added to generate max storage load test files (#2472)
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
"e2e:test:cicd:standalone": "xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' nx e2e:test:cicd:standalone mudita-center-e2e",
|
||||
"e2e:test:cicd:mock": "xvfb-run --auto-servernum --server-args='-screen 0 1024x768x24' nx e2e:test:cicd:mock mudita-center-e2e",
|
||||
"test-file:generate-and-push": "ts-node scripts/manage-test-files/generate-and-push-test-files.ts",
|
||||
"test-file:generate-max-storage-load": "ts-node scripts/manage-test-files/generate-max-storage-load.ts",
|
||||
"test-file:clear": "ts-node scripts/manage-test-files/clear-test-files.ts",
|
||||
"api-device-testing": "npx nx run api-devices-testing:test --skip-nx-cache"
|
||||
},
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
import { checkAdbAvailability, checkIfDeviceLocked, ensureSingleDevice, execPromise } from "./helpers"
|
||||
import {
|
||||
checkAdbAvailability,
|
||||
checkIfDeviceLocked,
|
||||
ensureSingleDevice,
|
||||
execPromise,
|
||||
} from "./helpers"
|
||||
import { getRemotePaths } from "./get-remote-paths"
|
||||
import {
|
||||
fileManagerTestFilesFolderName,
|
||||
lowStorageFolderName,
|
||||
RemotePathsTarget,
|
||||
} from "./manage-test-files.const"
|
||||
import { parseTargetArg } from "./parse-target-arg"
|
||||
|
||||
|
||||
async function clearTestFiles(): Promise<void> {
|
||||
async function clearDeviceDirectory(path: string): Promise<void> {
|
||||
try {
|
||||
console.log("Removing test files from the device...")
|
||||
const command = `adb shell rm -rf /storage/emulated/0/file-manager-test-files`
|
||||
console.log(`🧹 Removing files from ${path}...`)
|
||||
const command = `adb shell rm -rf "${path}"`
|
||||
const { stdout, stderr } = await execPromise(command)
|
||||
|
||||
if (stdout) console.log(`Output: ${stdout}`)
|
||||
if (stderr) console.error(`Error: ${stderr}`)
|
||||
console.log("Test files successfully removed from the device.")
|
||||
console.log(`✅ Files successfully removed from ${path}`)
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Failed to remove test files from the device. Ensure the device is connected and accessible via ADB.`
|
||||
`❌ Failed to remove files from ${path}:`,
|
||||
(err as Error).message
|
||||
)
|
||||
console.error(`Error Details: ${(err as Error).message}`)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +33,16 @@ async function main(): Promise<void> {
|
||||
await checkAdbAvailability()
|
||||
await ensureSingleDevice()
|
||||
await checkIfDeviceLocked()
|
||||
await clearTestFiles()
|
||||
|
||||
const target = parseTargetArg(process.argv.slice(2), RemotePathsTarget.both)
|
||||
const folders = [lowStorageFolderName, fileManagerTestFilesFolderName]
|
||||
|
||||
for (const folder of folders) {
|
||||
const paths = await getRemotePaths(target, folder)
|
||||
for (const path of paths) {
|
||||
await clearDeviceDirectory(path)
|
||||
}
|
||||
}
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
import sharp from "sharp"
|
||||
import fs from "fs-extra"
|
||||
import path from "path"
|
||||
import { checkAdbAvailability, checkIfDeviceLocked, ensureSingleDevice, pushToDevice, restartDevice } from "./helpers"
|
||||
import {
|
||||
checkAdbAvailability,
|
||||
checkIfDeviceLocked,
|
||||
ensureSingleDevice,
|
||||
pushToDevice,
|
||||
restartDevice,
|
||||
} from "./helpers"
|
||||
import { getRemotePaths } from "./get-remote-paths"
|
||||
import { fileManagerTestFilesFolderName } from "./manage-test-files.const"
|
||||
import { parseTargetArg } from "./parse-target-arg"
|
||||
|
||||
interface TestCase {
|
||||
name: string
|
||||
@@ -97,16 +106,30 @@ async function main(): Promise<void> {
|
||||
try {
|
||||
const testCases = await loadTestCases()
|
||||
|
||||
await checkAdbAvailability()
|
||||
await ensureSingleDevice()
|
||||
await checkIfDeviceLocked()
|
||||
|
||||
await fs.remove(outputDir)
|
||||
|
||||
await generateImageFiles(testCases.images)
|
||||
await generateAudioFiles(testCases.audio)
|
||||
await generateEBookFiles(testCases.ebooks)
|
||||
await generateAPKFiles(testCases.apk)
|
||||
|
||||
await checkAdbAvailability()
|
||||
await ensureSingleDevice()
|
||||
await checkIfDeviceLocked()
|
||||
await pushToDevice(outputDir)
|
||||
const target = parseTargetArg(process.argv.slice(2))
|
||||
|
||||
const remotePaths = await getRemotePaths(
|
||||
target,
|
||||
fileManagerTestFilesFolderName
|
||||
)
|
||||
|
||||
for (const remotePath of remotePaths) {
|
||||
await pushToDevice(outputDir, remotePath)
|
||||
}
|
||||
await restartDevice()
|
||||
|
||||
await fs.remove(outputDir)
|
||||
} catch (err) {
|
||||
console.error("Error during test file generation:", (err as Error).message)
|
||||
}
|
||||
|
||||
110
scripts/manage-test-files/generate-max-storage-load.ts
Normal file
110
scripts/manage-test-files/generate-max-storage-load.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
* Copyright (c) Mudita sp. z o.o. All rights reserved.
|
||||
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import {
|
||||
checkAdbAvailability,
|
||||
checkIfDeviceLocked,
|
||||
ensureSingleDevice,
|
||||
execPromise,
|
||||
} from "./helpers"
|
||||
import { getRemotePaths } from "./get-remote-paths"
|
||||
import { lowStorageFolderName } from "./manage-test-files.const"
|
||||
import { parseTargetArg } from "./parse-target-arg"
|
||||
|
||||
const partSizeBytes = 10 * 1024 ** 3 // 10 GB
|
||||
const targetFillSizeBytes = 100 * 1024 ** 3 // 100 GB
|
||||
|
||||
const writePart = async (
|
||||
bytes: number,
|
||||
remotePath: string,
|
||||
index: number
|
||||
): Promise<number> => {
|
||||
const mb = Math.floor(bytes / (1024 * 1024))
|
||||
const filename = `dummy_file_${mb}_${Date.now()}_${index}.bin`
|
||||
|
||||
console.log(`📦 Writing part ${index + 1}: ${mb} MB to ${remotePath}...`)
|
||||
|
||||
const start = Date.now()
|
||||
try {
|
||||
await execPromise(
|
||||
`adb shell 'dd if=/dev/zero of="${remotePath}/${filename}" bs=1M count=${mb}'`
|
||||
)
|
||||
const duration = ((Date.now() - start) / 1000).toFixed(1)
|
||||
console.log(`✅ Part ${index + 1} written successfully in ${duration}s`)
|
||||
return bytes
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`❌ Failed to write part ${index + 1} — likely due to lack of space.`
|
||||
)
|
||||
|
||||
try {
|
||||
const { stdout } = await execPromise(
|
||||
`adb shell ls -l "${remotePath}/${filename}"`
|
||||
)
|
||||
const parts = stdout.trim().split(/\s+/)
|
||||
const actualSize = parseInt(parts[4], 10)
|
||||
const duration = ((Date.now() - start) / 1000).toFixed(1)
|
||||
console.log(
|
||||
`ℹ️ Partial file created: ${(actualSize / 1024 ** 2).toFixed(
|
||||
2
|
||||
)} MB in ${duration}s`
|
||||
)
|
||||
return actualSize
|
||||
} catch {
|
||||
console.warn("⚠️ Could not determine partial file size.")
|
||||
return 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const simulateLowStorage = async (
|
||||
totalTargetBytes: number,
|
||||
remotePath: string
|
||||
): Promise<void> => {
|
||||
console.log(`📁 Creating directory at ${remotePath}...`)
|
||||
await execPromise(`adb shell mkdir -p "${remotePath}"`)
|
||||
|
||||
console.log("📊 Starting low storage simulation in 10 GB chunks...")
|
||||
let written = 0
|
||||
let index = 0
|
||||
|
||||
while (written < totalTargetBytes) {
|
||||
const remaining = totalTargetBytes - written
|
||||
const sizeToWrite = Math.min(partSizeBytes, remaining)
|
||||
const writtenNow = await writePart(sizeToWrite, remotePath, index)
|
||||
if (writtenNow === 0) break
|
||||
written += writtenNow
|
||||
index++
|
||||
}
|
||||
|
||||
console.log(
|
||||
`🏁 Done. Total written: ${(written / 1024 ** 3).toFixed(
|
||||
2
|
||||
)} GB in ${index} part(s).`
|
||||
)
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
await checkAdbAvailability()
|
||||
await ensureSingleDevice()
|
||||
await checkIfDeviceLocked()
|
||||
|
||||
const target = parseTargetArg(process.argv.slice(2))
|
||||
|
||||
const paths = await getRemotePaths(target, lowStorageFolderName)
|
||||
|
||||
console.log("📱 Simulating low storage on Kompakt device...")
|
||||
console.log(
|
||||
"ℹ️ This process can take several minutes depending on device speed."
|
||||
)
|
||||
console.log("💡 Example: Writing 10 GB takes ~1 minute on average.")
|
||||
|
||||
for (const path of paths) {
|
||||
await simulateLowStorage(targetFillSizeBytes, path)
|
||||
}
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
void main()
|
||||
64
scripts/manage-test-files/get-remote-paths.ts
Normal file
64
scripts/manage-test-files/get-remote-paths.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* Copyright (c) Mudita sp. z o.o. All rights reserved.
|
||||
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
|
||||
*/
|
||||
import { execPromise } from "./helpers"
|
||||
import { RemotePathsTarget } from "./manage-test-files.const"
|
||||
|
||||
async function getExternalStoragePath(folder: string): Promise<string | null> {
|
||||
try {
|
||||
const { stdout } = await execPromise(`adb shell ls /storage`)
|
||||
const candidates = stdout
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter((name) => /^[\w\d]{4}-[\w\d]{4}$/.test(name))
|
||||
|
||||
if (candidates.length === 0) {
|
||||
console.warn("⚠️ No external storage detected.")
|
||||
return null
|
||||
}
|
||||
|
||||
const selected = candidates[0]
|
||||
return `/storage/${selected}/DCIM/${folder}`
|
||||
} catch (err) {
|
||||
console.error(
|
||||
"❌ Failed to detect external storage:",
|
||||
(err as Error).message
|
||||
)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export async function getRemotePaths(
|
||||
target: RemotePathsTarget,
|
||||
folder: string
|
||||
): Promise<string[]> {
|
||||
const internalStoragePath = `/storage/emulated/0/${folder}`
|
||||
const paths: string[] = []
|
||||
|
||||
if (
|
||||
target === RemotePathsTarget.internal ||
|
||||
target === RemotePathsTarget.both
|
||||
) {
|
||||
paths.push(internalStoragePath)
|
||||
}
|
||||
|
||||
if (
|
||||
target === RemotePathsTarget.external ||
|
||||
target === RemotePathsTarget.both
|
||||
) {
|
||||
const externalPath = await getExternalStoragePath(folder)
|
||||
if (externalPath) {
|
||||
paths.push(externalPath)
|
||||
} else {
|
||||
console.warn("⚠️ Skipping external storage – path not found.")
|
||||
}
|
||||
}
|
||||
|
||||
if (paths.length === 0) {
|
||||
console.error("❌ No valid storage targets found.")
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
return paths
|
||||
}
|
||||
@@ -68,17 +68,19 @@ export async function checkIfDeviceLocked(): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushToDevice(outputDir: string): Promise<void> {
|
||||
export async function pushToDevice(
|
||||
outputDir: string,
|
||||
remotePath: string
|
||||
): Promise<void> {
|
||||
try {
|
||||
const command = `adb push ${outputDir} /storage/emulated/0/`
|
||||
const command = `adb push ${outputDir} ${remotePath}`
|
||||
const { stdout, stderr } = await execPromise(command)
|
||||
if (stdout) console.log(stdout)
|
||||
if (stderr) console.error(stderr)
|
||||
} catch (err) {
|
||||
console.error(
|
||||
`Failed to push files to the device. Ensure the device is connected and accessible via ADB.`
|
||||
`Failed to push files to the device: ${(err as Error).message}`
|
||||
)
|
||||
console.error(`Error Details: ${(err as Error).message}`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
13
scripts/manage-test-files/manage-test-files.const.ts
Normal file
13
scripts/manage-test-files/manage-test-files.const.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright (c) Mudita sp. z o.o. All rights reserved.
|
||||
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
export const lowStorageFolderName = "low-storage"
|
||||
export const fileManagerTestFilesFolderName = "file-manager-test-files"
|
||||
|
||||
export enum RemotePathsTarget {
|
||||
internal = "internal",
|
||||
external = "external",
|
||||
both = "both",
|
||||
}
|
||||
29
scripts/manage-test-files/parse-target-arg.ts
Normal file
29
scripts/manage-test-files/parse-target-arg.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Copyright (c) Mudita sp. z o.o. All rights reserved.
|
||||
* For licensing, see https://github.com/mudita/mudita-center/blob/master/LICENSE.md
|
||||
*/
|
||||
import { RemotePathsTarget } from "./manage-test-files.const"
|
||||
|
||||
export const parseTargetArg = (
|
||||
args: string[],
|
||||
fallback: RemotePathsTarget = RemotePathsTarget.internal
|
||||
): RemotePathsTarget => {
|
||||
const targetArg = args.find((arg) => arg.startsWith("--target="))
|
||||
const rawValue = targetArg?.split("=")[1]
|
||||
|
||||
const isValid = Object.values(RemotePathsTarget).includes(
|
||||
rawValue as RemotePathsTarget
|
||||
)
|
||||
|
||||
if (isValid) {
|
||||
return rawValue as RemotePathsTarget
|
||||
}
|
||||
|
||||
if (rawValue) {
|
||||
console.warn(
|
||||
`⚠️ Unknown target "${rawValue}", falling back to "${fallback}".`
|
||||
)
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
||||
Reference in New Issue
Block a user