ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:114942] [Ruby master Bug#19909] s390x zlib different deflate algorithm producing a different compressed byte stream causing test failures
@ 2023-10-02 15:26 jaruga (Jun Aruga) via ruby-core
  2023-10-04 15:49 ` [ruby-core:114947] " jaruga (Jun Aruga) via ruby-core
  0 siblings, 1 reply; 2+ messages in thread
From: jaruga (Jun Aruga) via ruby-core @ 2023-10-02 15:26 UTC (permalink / raw
  To: ruby-core; +Cc: jaruga (Jun Aruga)

Issue #19909 has been reported by jaruga (Jun Aruga).

----------------------------------------
Bug #19909: s390x zlib different deflate algorithm producing a different compressed byte stream causing test failures
https://bugs.ruby-lang.org/issues/19909

* Author: jaruga (Jun Aruga)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
I faced the test failures ruby/zlib (zlib gem) in `make test-all` and ruby/spec (`make test-spec`) in Ubuntu version jammy (22.04) s390x. I intend to manage this issue on this ticket, and giving the space for users to comment about the issue.

## The test failures

First, below are the test failures by `make test-all` and `make test-spec` on Ubuntu jammy s390x.

Here is the used zlib version.

```
$ dpkg -s "$(dpkg -S /usr/include/zlib.h | cut -d ":" -f 1)" | grep ^Version
Version: 1:1.2.11.dfsg-2ubuntu9.2
```

```
+ make -s test-all -o exts TESTOPTS=-j3 -q --tty=no  RUBYOPT=-w
generating enc.mk
making enc
making srcs under enc
generating transdb.h
transdb.h unchanged
making trans
making encs
Run options: 
  --seed=42873
  "--ruby=./miniruby -I../lib -I. -I.ext/common  ../tool/runruby.rb --extout=.ext  -- --disable-gems"
  --excludes-dir=../test/.excludes
  --name=!/memory_leak/
  -j3
  -q
  --tty=no

# Running tests:


Retrying...

  1) Failure:
TestZlibDeflate#test_deflate_chunked [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:66]:
<7253> expected but was
<8325>.

  2) Failure:
TestZlibDeflate#test_deflate_chunked_break [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:92]:
<3632> expected but was
<4702>.

  3) Failure:
TestZlibGzipReader#test_unused2 [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:968]:
<24> expected but was
<23>.

  4) Failure:
TestZlib#test_gzip [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:1419]:
<"\x1F\x8B\b\x00\x00\x00\x00\x00\x00\xFFK\xCB\xCF\a\x00!es\x8C\x03\x00\x00\x00"> expected but was
<"\x1F\x8B\b\x00\x00\x00\x00\x00\x00\xFFJ\xCB\xCF\a\f\x00!es\x8C\x03\x00\x00\x00">.

  5) Failure:
TestZlib#test_deflate_stream [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:1411]:
<20016> expected but was
<21085>.

Finished tests in 290.303048s, 88.4145 tests/s, 21049.4999 assertions/s.
25667 tests, 6110734 assertions, 5 failures, 0 errors, 172 skips
```

```
$SETARCH make -s test-spec
...
1)
Zlib::Deflate.deflate deflates some data FAILED
Expected 
"x\x9Cc\x80\x03\x00\x00
\x00\x01" == 
"x\x9Cc`\x80\x01\x00\x00
\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:10:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:4:in `<top (required)>'

2)
Zlib::Deflate.deflate deflates lots of data FAILED
Expected "x\x9Cc\x18\xE1`\xA4\x83\x91\x0Eh\rF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0E\x06;\x00\x00\x80\x00\x00\x01" == 
"x\x9C\xED\xC1\x01\x01\x00\x00\x00\x80\x90\xFE\xAF\xEE\b
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x80\x00\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:18:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:4:in `<top (required)>'

3)
Zlib::Deflate.deflate deflates chunked data FAILED
Expected 21085 == 20016
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:32:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:4:in `<top (required)>'

4)
Zlib::Deflate#deflate deflates some data FAILED
Expected 
"x\x9Cc\x80\x03\x00\x00
\x00\x01" == 
"x\x9Cc`\x80\x01\x00\x00
\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:47:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:36:in `<top (required)>'

5)
Zlib::Deflate#deflate deflates lots of data FAILED
Expected "x\x9Cc\x18\xE1`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x81\x06#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\f4\x00\x00\x80\x00\x00\x01" == 
"x\x9C\xED\xC1\x01\x01\x00\x00\x00\x80\x90\xFE\xAF\xEE\b
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x80\x00\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:56:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:36:in `<top (required)>'

6)
Zlib::Deflate#deflate without break deflates chunked data with final chunk FAILED
Expected 8325 == 7253
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:96:in `block (3 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:68:in `<top (required)>'

7)
Zlib::Deflate#deflate with break deflates chunked data with final chunk FAILED
Expected 4702 == 3632
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:123:in `block (3 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:68:in `<top (required)>'

8)
Zlib::Deflate#set_dictionary sets the dictionary FAILED
Expected "x\xBB\x14\xE1\x03\xCBJLJNIMK\xCF\xC8\xCC\x02\f\x00\x15\x86\x03\xF8" == "x\xBB\x14\xE1\x03\xCBKLJNIMK\xCF\xC8\xCC\x02\x00\x15\x86\x03\xF8"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb:10:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb:4:in `<top (required)>'

9)
Zlib.deflate deflates some data FAILED
Expected 
"x\x9C3\x84\x03\x00
\x91\x01\xEB" == 
"x\x9C34\x84\x01\x00
\x91\x01\xEB"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate_spec.rb:6:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate_spec.rb:4:in `<top (required)>'

10)
Zlib.gzip gzips the given string FAILED
Expected 
"24261MLJNI\x05\f\x00\x9D\x05\x00$
\x00\x00\x00" == 
"34261MLJNI\x05\x00\x9D\x05\x00$
\x00\x00\x00"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzip_spec.rb:13:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzip_spec.rb:4:in `<top (required)>'

11)
Zlib::GzipWriter#write writes some compressed data FAILED
Expected [50, 52, 50, 54, 49, 77, 76, 74, 78, 73, 5, 12, 0, 157, 5, 0, 36, 10, 0, 0, 0] == [51, 52, 50, 54, 49, 77, 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0]
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:19:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:5:in `<top (required)>'

12)
Zlib::GzipWriter#write handles inputs of 2^23 bytes FAILED
Expected 34263 == 8176
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:34:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:5:in `<top (required)>'

Finished in 114.477929 seconds

3715 files, 32609 examples, 190709 expectations, 12 failures, 0 errors, 0 tagged
```

## The root cause

This issue can happen with zlib library applying [the patch zlib/pull#410](https://github.com/madler/zlib/pull/410) that is to enable a different deflate algorithm producing a different compressed byte stream causing the test failures. I am not sure how a Ubuntu zlib deb package is developed in Ubuntu. However I was able to download and check the source file `zlib_1.2.11.dfsg-2ubuntu9.2.debian.tar.xz` on [the Ubuntu jammy-updates zlib deb package page](https://packages.ubuntu.com/jammy-updates/zlib1g).

debian/rules
```
...
 49 # s390x fails at compatibility.
 50 ifneq (,$(findstring $(DEB_HOST_ARCH), s390x))
 51 m32=-m31
 52 CFLAGS += -DDFLTCC_LEVEL_MASK=0x7e
 53 CONFIGURE_COMMON += --dfltcc
 54 CONFIGURE_HOST += --crc32-vx
 55 else
 56 m32=-m32
 57 endif
...
```

debian/patches/series
```
...
  4 410.patch
...
```

debian/patches/410.patch

```
From 992a7afc3edfa511dff0650d1c545b11bf64e655 Mon Sep 17 00:00:00 2001
From: Ilya Leoshkevich <iii@linux.ibm.com>
Date: Wed, 18 Jul 2018 13:14:07 +0200
Subject: [PATCH] Add support for IBM Z hardware-accelerated deflate
...
```

And the 410.patch is the [the patch zlib/pull#410](https://github.com/madler/zlib/pull/410) above.

## A reproducer

For convenience, here is a relatively small reproducer.

```
$ cat test/zlib/_test_zlib_test_deflate_chunked.rb
require 'zlib'

z = Zlib::Deflate.new
input = "\x01"
z.deflate(input) do |chunk|
end
final = z.finish
puts "final.length: #{final.length}"
```

Below is ok case.

```
$ ruby -I./lib test/zlib/_test_zlib_test_deflate_chunked.rb
final.length: 9
```

Below is the case with the zlib where the tests are failing in s390x.

```
$ ruby -I./lib test/zlib/_test_zlib_test_deflate_chunked.rb
final.length: 10
```

## Affected distributions and versions

Affected: at least Ubuntu jammy 22.04

I didn't see this issue in Ubuntu focal (20.04). The same `410.patch` is applied in both Ubuntu focal and jammy. But how to build is different. In Ubuntu jammy, the zlib is configured by `./configure --dfltcc`.

```
$ diff -u ubuntu_focal/zlib1g/debian/rules ubuntu_jammy/zlib1g/debian/rules
--- ubuntu_focal/zlib1g/debian/rules	2020-08-20 01:52:59.000000000 +0200
+++ ubuntu_jammy/zlib1g/debian/rules	2021-08-12 05:28:03.000000000 +0200
@@ -21,6 +21,9 @@
 LDFLAGS = `dpkg-buildflags --get LDFLAGS`
 EXTRA_MAKE =

+CONFIGURE_COMMON=--shared --prefix=/usr
+CONFIGURE_HOST=--libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)
+
 # binutils doesn't supply the prefixed version normally like GCC does so
 # we can't just unconditionally use DEB_HOST_GNU_TYPE-ar
 ifeq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
@@ -46,8 +49,9 @@
 # s390x fails at compatibility.
 ifneq (,$(findstring $(DEB_HOST_ARCH), s390x))
 m32=-m31
-CFLAGS += -DDFLTCC
-EXTRA_MAKE += OBJA=dfltcc.o PIC_OBJA=dfltcc.lo
+CFLAGS += -DDFLTCC_LEVEL_MASK=0x7e
+CONFIGURE_COMMON += --dfltcc
+CONFIGURE_HOST += --crc32-vx
 else
 m32=-m32
 endif
@@ -95,7 +99,7 @@

 	if [ ! -f Makefile.stash ]; then cp Makefile Makefile.stash ; fi

-	AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)
+	AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" uname=GNU ./configure $(CONFIGURE_COMMON) $(CONFIGURE_HOST)

 	touch $@

@@ -106,7 +110,7 @@
 	cp -r $(COPYLIST) debian/64
 	cd debian/64 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(m64)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr  --libdir=\$${prefix}/usr/lib64
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/lib64
 	touch $@

 configure32-stamp: configure
@@ -116,7 +120,7 @@
 	cp -r $(COPYLIST) debian/32
 	cd debian/32 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(m32)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/usr/lib32
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/lib32
 	touch $@

 configuren32-stamp: configure
@@ -126,7 +130,7 @@
 	cp -r $(COPYLIST) debian/n32
 	cd debian/n32 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(mn32)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/usr/lib32
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/lib32
 	touch $@

 configurex32-stamp: configure
@@ -136,7 +140,7 @@
 	cp -r $(COPYLIST) debian/x32
 	cd debian/x32 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(mx32)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/usr/libx32
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/libx32
 	touch $@

 build: build-stamp $(EXTRA_BUILD)
```

I also didn't see this issue with [the zlib RPM package](https://src.fedoraproject.org/rpms/zlib) in Fedora rawhide (Fedora 40), though I see the zlib is configured by `./configure --dfltcc` applying the patch `zlib-*-IBM-Z-hw-accelerated-deflate.patch`. But when comparing the `zlib-1.2.13-IBM-Z-hw-accelerated-deflate.patch` in the zlib in Fedora rawhide (Fedora 40), and `410.patch` in Ubuntu jammy-updates. It is quite different.

## Workaround

The patch author commented that a workaround is to set environment variable `DFLTCC=0` to disable the different deflate algorithm at [zlib/issues#60](https://github.com/ruby/zlib/issues/60#issuecomment-1733149916).

## How I fixed the issue with the workaround

* ruby/zlib: https://github.com/ruby/zlib/pull/65
* ruby/spec: https://github.com/ruby/spec/pull/1088
* ruby/ruby: https://github.com/ruby/ruby/pull/8401
* RubyCI - s390x (Ubuntu), the server is actually Ubuntu jammy, and the cron job is running with the `DFLTCC=0` in the crontab.

## How can we do?

The [upstream patch zlib/pull#410](https://github.com/madler/zlib/pull/410) is not merged to the zlib repository yet. And I am not sure if we want to do like this, modifying the `common.mk` (and `configure.ac`).

```
diff --git a/common.mk b/common.mk
index b8ae911ef2..2605569443 100644
--- a/common.mk
+++ b/common.mk
@@ -982,6 +982,7 @@ test-spec: $(TEST_RUNNABLE)-test-spec
 yes-test-spec: yes-test-spec-precheck
        $(ACTIONS_GROUP)
        $(gnumake_recursive)$(Q) \
+       DFLTCC=0 \
        $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/rubyspec_temp \
                $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/default.mspec $(MSPECOPT) $(SPECOPTS)
        $(ACTIONS_ENDGROUP)
```

So, it seems to me that just documenting this issue and workaround somewhere in ruby/ruby is a good fix for this issue.





-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* [ruby-core:114947] [Ruby master Bug#19909] s390x zlib different deflate algorithm producing a different compressed byte stream causing test failures
  2023-10-02 15:26 [ruby-core:114942] [Ruby master Bug#19909] s390x zlib different deflate algorithm producing a different compressed byte stream causing test failures jaruga (Jun Aruga) via ruby-core
@ 2023-10-04 15:49 ` jaruga (Jun Aruga) via ruby-core
  0 siblings, 0 replies; 2+ messages in thread
From: jaruga (Jun Aruga) via ruby-core @ 2023-10-04 15:49 UTC (permalink / raw
  To: ruby-core; +Cc: jaruga (Jun Aruga)

Issue #19909 has been updated by jaruga (Jun Aruga).


I sent PR to ruby/ruby to document this issue.
https://github.com/ruby/ruby/pull/8589


----------------------------------------
Bug #19909: s390x zlib different deflate algorithm producing a different compressed byte stream causing test failures
https://bugs.ruby-lang.org/issues/19909#change-104818

* Author: jaruga (Jun Aruga)
* Status: Open
* Priority: Normal
* Backport: 3.0: UNKNOWN, 3.1: UNKNOWN, 3.2: UNKNOWN
----------------------------------------
I faced the test failures ruby/zlib (zlib gem) in `make test-all` and ruby/spec (`make test-spec`) in Ubuntu version jammy (22.04) s390x. I intend to manage this issue on this ticket, and giving the space for users to comment about the issue.

## The test failures

First, below are the test failures by `make test-all` and `make test-spec` on Ubuntu jammy s390x.

Here is the used zlib version.

```
$ dpkg -s "$(dpkg -S /usr/include/zlib.h | cut -d ":" -f 1)" | grep ^Version
Version: 1:1.2.11.dfsg-2ubuntu9.2
```

```
+ make -s test-all -o exts TESTOPTS=-j3 -q --tty=no  RUBYOPT=-w
generating enc.mk
making enc
making srcs under enc
generating transdb.h
transdb.h unchanged
making trans
making encs
Run options: 
  --seed=42873
  "--ruby=./miniruby -I../lib -I. -I.ext/common  ../tool/runruby.rb --extout=.ext  -- --disable-gems"
  --excludes-dir=../test/.excludes
  --name=!/memory_leak/
  -j3
  -q
  --tty=no

# Running tests:


Retrying...

  1) Failure:
TestZlibDeflate#test_deflate_chunked [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:66]:
<7253> expected but was
<8325>.

  2) Failure:
TestZlibDeflate#test_deflate_chunked_break [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:92]:
<3632> expected but was
<4702>.

  3) Failure:
TestZlibGzipReader#test_unused2 [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:968]:
<24> expected but was
<23>.

  4) Failure:
TestZlib#test_gzip [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:1419]:
<"\x1F\x8B\b\x00\x00\x00\x00\x00\x00\xFFK\xCB\xCF\a\x00!es\x8C\x03\x00\x00\x00"> expected but was
<"\x1F\x8B\b\x00\x00\x00\x00\x00\x00\xFFJ\xCB\xCF\a\f\x00!es\x8C\x03\x00\x00\x00">.

  5) Failure:
TestZlib#test_deflate_stream [/home/travis/build/junaruga/ruby/test/zlib/test_zlib.rb:1411]:
<20016> expected but was
<21085>.

Finished tests in 290.303048s, 88.4145 tests/s, 21049.4999 assertions/s.
25667 tests, 6110734 assertions, 5 failures, 0 errors, 172 skips
```

```
$SETARCH make -s test-spec
...
1)
Zlib::Deflate.deflate deflates some data FAILED
Expected 
"x\x9Cc\x80\x03\x00\x00
\x00\x01" == 
"x\x9Cc`\x80\x01\x00\x00
\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:10:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:4:in `<top (required)>'

2)
Zlib::Deflate.deflate deflates lots of data FAILED
Expected "x\x9Cc\x18\xE1`\xA4\x83\x91\x0Eh\rF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x91\x0E\x06;\x00\x00\x80\x00\x00\x01" == 
"x\x9C\xED\xC1\x01\x01\x00\x00\x00\x80\x90\xFE\xAF\xEE\b
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x80\x00\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:18:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:4:in `<top (required)>'

3)
Zlib::Deflate.deflate deflates chunked data FAILED
Expected 21085 == 20016
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:32:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:4:in `<top (required)>'

4)
Zlib::Deflate#deflate deflates some data FAILED
Expected 
"x\x9Cc\x80\x03\x00\x00
\x00\x01" == 
"x\x9Cc`\x80\x01\x00\x00
\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:47:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:36:in `<top (required)>'

5)
Zlib::Deflate#deflate deflates lots of data FAILED
Expected "x\x9Cc\x18\xE1`\xA4\x83\x91\x0EF:\x18\xE9`\xA4\x83\x81\x06#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\x8Ct0\xD2\xC1H\a#\x1D\f4\x00\x00\x80\x00\x00\x01" == 
"x\x9C\xED\xC1\x01\x01\x00\x00\x00\x80\x90\xFE\xAF\xEE\b
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x18\x80\x00\x00\x01"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:56:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:36:in `<top (required)>'

6)
Zlib::Deflate#deflate without break deflates chunked data with final chunk FAILED
Expected 8325 == 7253
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:96:in `block (3 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:68:in `<top (required)>'

7)
Zlib::Deflate#deflate with break deflates chunked data with final chunk FAILED
Expected 4702 == 3632
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:123:in `block (3 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/deflate_spec.rb:68:in `<top (required)>'

8)
Zlib::Deflate#set_dictionary sets the dictionary FAILED
Expected "x\xBB\x14\xE1\x03\xCBJLJNIMK\xCF\xC8\xCC\x02\f\x00\x15\x86\x03\xF8" == "x\xBB\x14\xE1\x03\xCBKLJNIMK\xCF\xC8\xCC\x02\x00\x15\x86\x03\xF8"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb:10:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate/set_dictionary_spec.rb:4:in `<top (required)>'

9)
Zlib.deflate deflates some data FAILED
Expected 
"x\x9C3\x84\x03\x00
\x91\x01\xEB" == 
"x\x9C34\x84\x01\x00
\x91\x01\xEB"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate_spec.rb:6:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/deflate_spec.rb:4:in `<top (required)>'

10)
Zlib.gzip gzips the given string FAILED
Expected 
"24261MLJNI\x05\f\x00\x9D\x05\x00$
\x00\x00\x00" == 
"34261MLJNI\x05\x00\x9D\x05\x00$
\x00\x00\x00"
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzip_spec.rb:13:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzip_spec.rb:4:in `<top (required)>'

11)
Zlib::GzipWriter#write writes some compressed data FAILED
Expected [50, 52, 50, 54, 49, 77, 76, 74, 78, 73, 5, 12, 0, 157, 5, 0, 36, 10, 0, 0, 0] == [51, 52, 50, 54, 49, 77, 76, 74, 78, 73, 5, 0, 157, 5, 0, 36, 10, 0, 0, 0]
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:19:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:5:in `<top (required)>'

12)
Zlib::GzipWriter#write handles inputs of 2^23 bytes FAILED
Expected 34263 == 8176
to be truthy but was false
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:34:in `block (2 levels) in <top (required)>'
/home/travis/build/junaruga/ruby/spec/ruby/library/zlib/gzipwriter/write_spec.rb:5:in `<top (required)>'

Finished in 114.477929 seconds

3715 files, 32609 examples, 190709 expectations, 12 failures, 0 errors, 0 tagged
```

## The root cause

This issue can happen with zlib library applying [the patch zlib/pull#410](https://github.com/madler/zlib/pull/410) that is to enable a different deflate algorithm producing a different compressed byte stream causing the test failures. I am not sure how a Ubuntu zlib deb package is developed in Ubuntu. However I was able to download and check the source file `zlib_1.2.11.dfsg-2ubuntu9.2.debian.tar.xz` on [the Ubuntu jammy-updates zlib deb package page](https://packages.ubuntu.com/jammy-updates/zlib1g).

debian/rules
```
...
 49 # s390x fails at compatibility.
 50 ifneq (,$(findstring $(DEB_HOST_ARCH), s390x))
 51 m32=-m31
 52 CFLAGS += -DDFLTCC_LEVEL_MASK=0x7e
 53 CONFIGURE_COMMON += --dfltcc
 54 CONFIGURE_HOST += --crc32-vx
 55 else
 56 m32=-m32
 57 endif
...
```

debian/patches/series
```
...
  4 410.patch
...
```

debian/patches/410.patch

```
From 992a7afc3edfa511dff0650d1c545b11bf64e655 Mon Sep 17 00:00:00 2001
From: Ilya Leoshkevich <iii@linux.ibm.com>
Date: Wed, 18 Jul 2018 13:14:07 +0200
Subject: [PATCH] Add support for IBM Z hardware-accelerated deflate
...
```

And the 410.patch is the [the patch zlib/pull#410](https://github.com/madler/zlib/pull/410) above.

## A reproducer

For convenience, here is a relatively small reproducer.

```
$ cat test/zlib/_test_zlib_test_deflate_chunked.rb
require 'zlib'

z = Zlib::Deflate.new
input = "\x01"
z.deflate(input) do |chunk|
end
final = z.finish
puts "final.length: #{final.length}"
```

Below is ok case.

```
$ ruby -I./lib test/zlib/_test_zlib_test_deflate_chunked.rb
final.length: 9
```

Below is the case with the zlib where the tests are failing in s390x.

```
$ ruby -I./lib test/zlib/_test_zlib_test_deflate_chunked.rb
final.length: 10
```

## Affected distributions and versions

Affected: at least Ubuntu jammy 22.04

I didn't see this issue in Ubuntu focal (20.04). The same `410.patch` is applied in both Ubuntu focal and jammy. But how to build is different. In Ubuntu jammy, the zlib is configured by `./configure --dfltcc`.

```
$ diff -u ubuntu_focal/zlib1g/debian/rules ubuntu_jammy/zlib1g/debian/rules
--- ubuntu_focal/zlib1g/debian/rules	2020-08-20 01:52:59.000000000 +0200
+++ ubuntu_jammy/zlib1g/debian/rules	2021-08-12 05:28:03.000000000 +0200
@@ -21,6 +21,9 @@
 LDFLAGS = `dpkg-buildflags --get LDFLAGS`
 EXTRA_MAKE =

+CONFIGURE_COMMON=--shared --prefix=/usr
+CONFIGURE_HOST=--libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)
+
 # binutils doesn't supply the prefixed version normally like GCC does so
 # we can't just unconditionally use DEB_HOST_GNU_TYPE-ar
 ifeq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
@@ -46,8 +49,9 @@
 # s390x fails at compatibility.
 ifneq (,$(findstring $(DEB_HOST_ARCH), s390x))
 m32=-m31
-CFLAGS += -DDFLTCC
-EXTRA_MAKE += OBJA=dfltcc.o PIC_OBJA=dfltcc.lo
+CFLAGS += -DDFLTCC_LEVEL_MASK=0x7e
+CONFIGURE_COMMON += --dfltcc
+CONFIGURE_HOST += --crc32-vx
 else
 m32=-m32
 endif
@@ -95,7 +99,7 @@

 	if [ ! -f Makefile.stash ]; then cp Makefile Makefile.stash ; fi

-	AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)
+	AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc" CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" uname=GNU ./configure $(CONFIGURE_COMMON) $(CONFIGURE_HOST)

 	touch $@

@@ -106,7 +110,7 @@
 	cp -r $(COPYLIST) debian/64
 	cd debian/64 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(m64)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr  --libdir=\$${prefix}/usr/lib64
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/lib64
 	touch $@

 configure32-stamp: configure
@@ -116,7 +120,7 @@
 	cp -r $(COPYLIST) debian/32
 	cd debian/32 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(m32)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/usr/lib32
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/lib32
 	touch $@

 configuren32-stamp: configure
@@ -126,7 +130,7 @@
 	cp -r $(COPYLIST) debian/n32
 	cd debian/n32 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(mn32)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/usr/lib32
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/lib32
 	touch $@

 configurex32-stamp: configure
@@ -136,7 +140,7 @@
 	cp -r $(COPYLIST) debian/x32
 	cd debian/x32 && AR=$(AR) CC="$(DEB_HOST_GNU_TYPE)-gcc $(mx32)" \
 	    CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" \
-	    uname=GNU ./configure --shared --prefix=/usr --libdir=\$${prefix}/usr/libx32
+	    uname=GNU ./configure $(CONFIGURE_COMMON) --libdir=\$${prefix}/usr/libx32
 	touch $@

 build: build-stamp $(EXTRA_BUILD)
```

I also didn't see this issue with [the zlib RPM package](https://src.fedoraproject.org/rpms/zlib) in Fedora rawhide (Fedora 40), though I see the zlib is configured by `./configure --dfltcc` applying the patch `zlib-*-IBM-Z-hw-accelerated-deflate.patch`. But when comparing the `zlib-1.2.13-IBM-Z-hw-accelerated-deflate.patch` in the zlib in Fedora rawhide (Fedora 40), and `410.patch` in Ubuntu jammy-updates. It is quite different.

## Workaround

The patch author commented that a workaround is to set environment variable `DFLTCC=0` to disable the different deflate algorithm at [zlib/issues#60](https://github.com/ruby/zlib/issues/60#issuecomment-1733149916).

## How I fixed the issue with the workaround

* ruby/zlib: https://github.com/ruby/zlib/pull/65
* ruby/spec: https://github.com/ruby/spec/pull/1088
* ruby/ruby: https://github.com/ruby/ruby/pull/8401
* RubyCI - s390x (Ubuntu), the server is actually Ubuntu jammy, and the cron job is running with the `DFLTCC=0` in the crontab.

## How can we do?

The [upstream patch zlib/pull#410](https://github.com/madler/zlib/pull/410) is not merged to the zlib repository yet. And I am not sure if we want to do like this, modifying the `common.mk` (and `configure.ac`).

```
diff --git a/common.mk b/common.mk
index b8ae911ef2..2605569443 100644
--- a/common.mk
+++ b/common.mk
@@ -982,6 +982,7 @@ test-spec: $(TEST_RUNNABLE)-test-spec
 yes-test-spec: yes-test-spec-precheck
        $(ACTIONS_GROUP)
        $(gnumake_recursive)$(Q) \
+       DFLTCC=0 \
        $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/rubyspec_temp \
                $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/default.mspec $(MSPECOPT) $(SPECOPTS)
        $(ACTIONS_ENDGROUP)
```

So, it seems to me that just documenting this issue and workaround somewhere in ruby/ruby is a good fix for this issue.





-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2023-10-04 15:49 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-10-02 15:26 [ruby-core:114942] [Ruby master Bug#19909] s390x zlib different deflate algorithm producing a different compressed byte stream causing test failures jaruga (Jun Aruga) via ruby-core
2023-10-04 15:49 ` [ruby-core:114947] " jaruga (Jun Aruga) via ruby-core

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).