Skip to content

Commit

Permalink
Merge branch 'master' into infra/shellcheck
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Nov 20, 2024
2 parents 90a487f + 32b5d74 commit 53ede77
Show file tree
Hide file tree
Showing 133 changed files with 3,522 additions and 125 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ jobs:

dist_darwin:
macos:
xcode: 13.4.1
xcode: 15.3.0
shell: /bin/bash --login -eo pipefail
steps:
- restore_cache:
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ jobs:
DOCKER_TEST_PREFIX: crystallang/crystal:${{ matrix.crystal_bootstrap_version }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
crystal_bootstrap_version: [1.7.3, 1.8.2, 1.9.2, 1.10.1, 1.11.2, 1.12.2, 1.13.3, 1.14.0]
flags: [""]
Expand Down
45 changes: 22 additions & 23 deletions .github/workflows/mingw-w64.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ jobs:
- name: Download Crystal source
uses: actions/checkout@v4

- name: Install LLVM 18
- name: Install LLVM
run: |
_llvm_major=$(wget -qO- https://raw.githubusercontent.com/msys2/MINGW-packages/refs/heads/master/mingw-w64-llvm/PKGBUILD | grep '_version=' | sed -E 's/_version=([0-9]+).*/\1/')
sudo apt remove 'llvm-*' 'libllvm*'
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
sudo apt-add-repository -y deb http://apt.llvm.org/noble/ llvm-toolchain-noble-18 main
sudo apt install -y llvm-18-dev
sudo apt-add-repository -y deb http://apt.llvm.org/noble/ llvm-toolchain-noble-${_llvm_major} main
sudo apt install -y llvm-${_llvm_major}-dev
- name: Install Crystal
uses: crystal-lang/install-crystal@v1
Expand All @@ -39,12 +40,6 @@ jobs:
name: x86_64-mingw-w64-crystal-obj
path: .build/crystal.obj

- name: Upload standard library
uses: actions/upload-artifact@v4
with:
name: x86_64-mingw-w64-crystal-stdlib
path: src

x86_64-mingw-w64-link:
runs-on: windows-2022
needs: [x86_64-mingw-w64-cross-compile]
Expand All @@ -56,6 +51,7 @@ jobs:
msystem: UCRT64
update: true
install: >-
make
mingw-w64-ucrt-x86_64-pkgconf
mingw-w64-ucrt-x86_64-cc
mingw-w64-ucrt-x86_64-gc
Expand All @@ -65,34 +61,37 @@ jobs:
mingw-w64-ucrt-x86_64-llvm
mingw-w64-ucrt-x86_64-libffi
- name: Disable CRLF line ending substitution
run: |
git config --global core.autocrlf false
- name: Download Crystal source
uses: actions/checkout@v4

- name: Download crystal.obj
uses: actions/download-artifact@v4
with:
name: x86_64-mingw-w64-crystal-obj

- name: Download standard library
uses: actions/download-artifact@v4
with:
name: x86_64-mingw-w64-crystal-stdlib
path: share/crystal/src

- name: Link Crystal executable
shell: msys2 {0}
run: |
mkdir bin
cc crystal.obj -o bin/crystal.exe \
mkdir .build
cc crystal.obj -o .build/crystal.exe -municode \
$(pkg-config bdw-gc libpcre2-8 iconv zlib libffi --libs) \
$(llvm-config --libs --system-libs --ldflags) \
-lDbgHelp -lole32 -lWS2_32 -Wl,--stack,0x800000
ldd bin/crystal.exe | grep -iv /c/windows/system32 | sed 's/.* => //; s/ (.*//' | xargs -t -i cp '{}' bin/
-lole32 -lWS2_32 -Wl,--stack,0x800000
- name: Upload Crystal
- name: Package Crystal
shell: msys2 {0}
run: |
make install install_dlls deref_symlinks=1 PREFIX="$(pwd)/crystal"
- name: Upload Crystal executable
uses: actions/upload-artifact@v4
with:
name: x86_64-mingw-w64-crystal
path: |
bin/
share/
path: crystal

x86_64-mingw-w64-test:
runs-on: windows-2022
Expand Down
226 changes: 226 additions & 0 deletions spec/std/crystal/evented/arena_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
{% skip_file unless Crystal.has_constant?(:Evented) %}

require "spec"

describe Crystal::Evented::Arena do
describe "#allocate_at?" do
it "yields block when not allocated" do
arena = Crystal::Evented::Arena(Int32).new(32)
pointer = nil
index = nil
called = 0

ret = arena.allocate_at?(0) do |ptr, idx|
pointer = ptr
index = idx
called += 1
end
ret.should eq(index)
called.should eq(1)

ret = arena.allocate_at?(0) { called += 1 }
ret.should be_nil
called.should eq(1)

pointer.should_not be_nil
index.should_not be_nil

arena.get(index.not_nil!) do |ptr|
ptr.should eq(pointer)
end
end

it "allocates up to capacity" do
arena = Crystal::Evented::Arena(Int32).new(32)
indexes = [] of Crystal::Evented::Arena::Index

indexes = 32.times.map do |i|
arena.allocate_at?(i) { |ptr, _| ptr.value = i }
end.to_a

indexes.size.should eq(32)

indexes.each do |index|
arena.get(index.not_nil!) do |pointer|
pointer.should eq(pointer)
pointer.value.should eq(index.not_nil!.index)
end
end
end

it "checks bounds" do
arena = Crystal::Evented::Arena(Int32).new(32)
expect_raises(IndexError) { arena.allocate_at?(-1) { } }
expect_raises(IndexError) { arena.allocate_at?(33) { } }
end
end

describe "#get" do
it "returns previously allocated object" do
arena = Crystal::Evented::Arena(Int32).new(32)
pointer = nil

index = arena.allocate_at(30) do |ptr|
pointer = ptr
ptr.value = 654321
end
called = 0

2.times do
arena.get(index.not_nil!) do |ptr|
ptr.should eq(pointer)
ptr.value.should eq(654321)
called += 1
end
end
called.should eq(2)
end

it "can't access unallocated object" do
arena = Crystal::Evented::Arena(Int32).new(32)

expect_raises(RuntimeError) do
arena.get(Crystal::Evented::Arena::Index.new(10, 0)) { }
end
end

it "checks generation" do
arena = Crystal::Evented::Arena(Int32).new(32)
called = 0

index1 = arena.allocate_at(2) { called += 1 }
called.should eq(1)

arena.free(index1) { }
expect_raises(RuntimeError) { arena.get(index1) { } }

index2 = arena.allocate_at(2) { called += 1 }
called.should eq(2)
expect_raises(RuntimeError) { arena.get(index1) { } }

arena.get(index2) { }
end

it "checks out of bounds" do
arena = Crystal::Evented::Arena(Int32).new(32)
expect_raises(IndexError) { arena.get(Crystal::Evented::Arena::Index.new(-1, 0)) { } }
expect_raises(IndexError) { arena.get(Crystal::Evented::Arena::Index.new(33, 0)) { } }
end
end

describe "#get?" do
it "returns previously allocated object" do
arena = Crystal::Evented::Arena(Int32).new(32)
pointer = nil

index = arena.allocate_at(30) do |ptr|
pointer = ptr
ptr.value = 654321
end

called = 0
2.times do
ret = arena.get?(index) do |ptr|
ptr.should eq(pointer)
ptr.not_nil!.value.should eq(654321)
called += 1
end
ret.should be_true
end
called.should eq(2)
end

it "can't access unallocated index" do
arena = Crystal::Evented::Arena(Int32).new(32)

called = 0
ret = arena.get?(Crystal::Evented::Arena::Index.new(10, 0)) { called += 1 }
ret.should be_false
called.should eq(0)
end

it "checks generation" do
arena = Crystal::Evented::Arena(Int32).new(32)
called = 0

old_index = arena.allocate_at(2) { }
arena.free(old_index) { }

# not accessible after free:
ret = arena.get?(old_index) { called += 1 }
ret.should be_false
called.should eq(0)

# can be reallocated:
new_index = arena.allocate_at(2) { }

# still not accessible after reallocate:
ret = arena.get?(old_index) { called += 1 }
ret.should be_false
called.should eq(0)

# accessible after reallocate (new index):
ret = arena.get?(new_index) { called += 1 }
ret.should be_true
called.should eq(1)
end

it "checks out of bounds" do
arena = Crystal::Evented::Arena(Int32).new(32)
called = 0

arena.get?(Crystal::Evented::Arena::Index.new(-1, 0)) { called += 1 }.should be_false
arena.get?(Crystal::Evented::Arena::Index.new(33, 0)) { called += 1 }.should be_false

called.should eq(0)
end
end

describe "#free" do
it "deallocates the object" do
arena = Crystal::Evented::Arena(Int32).new(32)

index1 = arena.allocate_at(3) { |ptr| ptr.value = 123 }
arena.free(index1) { }

index2 = arena.allocate_at(3) { }
index2.should_not eq(index1)

value = nil
arena.get(index2) { |ptr| value = ptr.value }
value.should eq(0)
end

it "checks generation" do
arena = Crystal::Evented::Arena(Int32).new(32)

called = 0
old_index = arena.allocate_at(1) { }

# can free:
arena.free(old_index) { called += 1 }
called.should eq(1)

# can reallocate:
new_index = arena.allocate_at(1) { }

# can't free with invalid index:
arena.free(old_index) { called += 1 }
called.should eq(1)

# but new index can:
arena.free(new_index) { called += 1 }
called.should eq(2)
end

it "checks out of bounds" do
arena = Crystal::Evented::Arena(Int32).new(32)
called = 0

arena.free(Crystal::Evented::Arena::Index.new(-1, 0)) { called += 1 }
arena.free(Crystal::Evented::Arena::Index.new(33, 0)) { called += 1 }

called.should eq(0)
end
end
end
Loading

0 comments on commit 53ede77

Please sign in to comment.