mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 01:01:39 -05:00
95 lines
2.7 KiB
Ruby
95 lines
2.7 KiB
Ruby
|
|
# frozen_string_literal: true
|
||
|
|
|
||
|
|
require 'rails_helper'
|
||
|
|
|
||
|
|
RSpec.describe Points::RawData::ChunkCompressor do
|
||
|
|
let(:user) { create(:user) }
|
||
|
|
|
||
|
|
before do
|
||
|
|
# Stub broadcasting to avoid ActionCable issues in tests
|
||
|
|
allow(PointsChannel).to receive(:broadcast_to)
|
||
|
|
end
|
||
|
|
let(:points) do
|
||
|
|
[
|
||
|
|
create(:point, user: user, raw_data: { lon: 13.4, lat: 52.5 }),
|
||
|
|
create(:point, user: user, raw_data: { lon: 13.5, lat: 52.6 }),
|
||
|
|
create(:point, user: user, raw_data: { lon: 13.6, lat: 52.7 })
|
||
|
|
]
|
||
|
|
end
|
||
|
|
let(:compressor) { described_class.new(Point.where(id: points.map(&:id))) }
|
||
|
|
|
||
|
|
describe '#compress' do
|
||
|
|
it 'returns compressed gzip data' do
|
||
|
|
result = compressor.compress
|
||
|
|
expect(result).to be_a(String)
|
||
|
|
expect(result.encoding.name).to eq('ASCII-8BIT')
|
||
|
|
end
|
||
|
|
|
||
|
|
it 'compresses points as JSONL format' do
|
||
|
|
compressed = compressor.compress
|
||
|
|
|
||
|
|
# Decompress and verify format
|
||
|
|
io = StringIO.new(compressed)
|
||
|
|
gz = Zlib::GzipReader.new(io)
|
||
|
|
lines = gz.readlines
|
||
|
|
gz.close
|
||
|
|
|
||
|
|
expect(lines.count).to eq(3)
|
||
|
|
|
||
|
|
# Each line should be valid JSON
|
||
|
|
lines.each_with_index do |line, index|
|
||
|
|
data = JSON.parse(line)
|
||
|
|
expect(data).to have_key('id')
|
||
|
|
expect(data).to have_key('raw_data')
|
||
|
|
expect(data['id']).to eq(points[index].id)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
it 'includes point ID and raw_data in each line' do
|
||
|
|
compressed = compressor.compress
|
||
|
|
|
||
|
|
io = StringIO.new(compressed)
|
||
|
|
gz = Zlib::GzipReader.new(io)
|
||
|
|
first_line = gz.readline
|
||
|
|
gz.close
|
||
|
|
|
||
|
|
data = JSON.parse(first_line)
|
||
|
|
expect(data['id']).to eq(points.first.id)
|
||
|
|
expect(data['raw_data']).to eq({ 'lon' => 13.4, 'lat' => 52.5 })
|
||
|
|
end
|
||
|
|
|
||
|
|
it 'processes points in batches' do
|
||
|
|
# Create many points to test batch processing with unique timestamps
|
||
|
|
many_points = []
|
||
|
|
base_time = Time.new(2024, 6, 15).to_i
|
||
|
|
2500.times do |i|
|
||
|
|
many_points << create(:point, user: user, timestamp: base_time + i, raw_data: { lon: 13.4, lat: 52.5 })
|
||
|
|
end
|
||
|
|
large_compressor = described_class.new(Point.where(id: many_points.map(&:id)))
|
||
|
|
|
||
|
|
compressed = large_compressor.compress
|
||
|
|
|
||
|
|
io = StringIO.new(compressed)
|
||
|
|
gz = Zlib::GzipReader.new(io)
|
||
|
|
line_count = 0
|
||
|
|
gz.each_line { line_count += 1 }
|
||
|
|
gz.close
|
||
|
|
|
||
|
|
expect(line_count).to eq(2500)
|
||
|
|
end
|
||
|
|
|
||
|
|
it 'produces smaller compressed output than uncompressed' do
|
||
|
|
compressed = compressor.compress
|
||
|
|
|
||
|
|
# Decompress to get original size
|
||
|
|
io = StringIO.new(compressed)
|
||
|
|
gz = Zlib::GzipReader.new(io)
|
||
|
|
decompressed = gz.read
|
||
|
|
gz.close
|
||
|
|
|
||
|
|
# Compressed should be smaller
|
||
|
|
expect(compressed.bytesize).to be < decompressed.bytesize
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|