2023年5月

新版本的 Voyager Linux 23.04 已经来到,我率先试驾以了解更多信息。

在我去年年初上次 测评 时,它还是一个崭露头角的发行版,提供了很棒的 Ubuntu LTS 体验。从那时起,这个发行版的方向发生了一些变化。因此,我觉得是时候进行另一轮试驾了。

顺便说一句,Voyager Linux 基于 Ubuntu Linux,针对 GNOME 桌面进行了出色的定制。之前,它只跟随 Ubuntu 长期支持(LTS)版本发布,但从去年开始,它也可跟随短期 Ubuntu 版本发布。

Ubuntu 23.04 “Lunar Lobster” 发布后,Voyager 团队宣布发布了 Voyager 23.04。

Voyager Linux 23.04 测评

与 Voyager 22.04 版本相比,此版本的 ISO 大小增加了约 30%。这可能主要是由于 Ubuntu 自己的软件包库。安装很顺利,但安装程序需要至少 24 GB 的存储空间(硬性要求)。但是,它使用旧的 Uniquity 安装程序,而不是新的基于 Flutter 的 Ubuntu 安装程序。

外观及使用感受

如果你运行的是早期版本的 Voyager Linux,你首先会注意到新版的外观精美。GNOME 桌面现在更具个性化,使用了 “Kora” 主题和许多扩展程序。

Voyager 23.04 桌面(GNOME)

在底部,你可以看到默认的程序坞,并通过 “Blur my shell” 扩展将其变成了透明的。此外,这一版本还预装了一系列扩展,并通过适当的设置启用,以便让 GNOME 桌面更好看。

值得重点一提的扩展是非常棒的 “Arc Menu”,可以下拉访问所有系统应用程序和资源。此外,“Dash to Dock”、“Blur my shell” 和 “Battery Indicator” 也是一些很有用的扩展应用。以下是 Voyager Linux 23.04 中预装的扩展列表:

  • Arch menu
  • Battery time
  • Blur my shell
  • Burn my windows
  • Caffeine
  • Clipboard history
  • Compiz alike magic lamp effect
  • Compiz windows effect
  • Custom hot corners – Extended
  • Dash to Dock
  • Desktop Cube
  • EasyScreenCast
  • Gradient Top Bar
  • Lock keys
  • Replace Activities Label
  • Screen Rotate
  • SettingsCenter
  • Simple net speed
  • Space Bar
  • Sur Clock
  • Use Avatar in Quick Settings

所有这些都使桌面在美观的同时超级高效。

带工作区示图的 Arc Menu

应用、Snap 和 Flatpak

尽管 Voyager Linux 是基于 Ubuntu 的,但默认情况下完全不包含 Snap。此外,Voyager Linux 23.04 也没有支持 Ubuntu 从该版本开始删除 Flatpak 的决定。因此,总而言之,Voyager Linux 23.04 中默认支持的是 Flatpak,而没有任何 Snap 的痕迹。不仅如此,Firefox 网络浏览器是由原生 deb 模块打包的,而不是 Snap 版本。

Voyager Linux 23.04 自带默认 Flatpak

应用程序列表很庞大且健全。主要应用程序包括 Gedit 文本编辑器、“文件”应用、Firefox 网络浏览器、GIMP 和 LibreOffice 套件。还包括 Thunderbird 电子邮件客户端、Remmina 远程连接应用程序、Transmission Torrent 客户端和 Pidgin 通讯软件。

Voyager 包括 Pitivi、MPV 和 Rhythmbox,均可用于播放视频和音乐。对于工作和文档处理,它提供了地图、日历、Foliate 阅读器应用程序、KeePassXC 和 Scrcpy 安卓屏幕镜像工具。

由于主 ISO 文件包括了 Xfce 和 GNOME 桌面,因此你也可以体验一些原生 Xfce 应用程序。

Voyager Linux Xfce 版本(23.04)

Box Voyager

Voyager Linux 带有自己的很棒的小应用,称为 “Box Voyager”,它让你可以一键访问所有桌面自定义设置。它有一个配置项列表,你可以直接使用此应用程序启动相应的设置。

此外,要进行更多自定义设置,你可以使用 Voyager Linux 中预装的多个 Conky 主题。 无需面对安装和配置 Conky 的麻烦。(LCTT 译注:Conky 是一个应用于桌面环境的系统监视软件,可以在桌面上监控系统运行状态、网络状态等一系列参数,而且可自由定制。)

Box Voyager 和 Conky Control

性能表现

安装了所有定制和扩展后,其性能表现令人印象深刻。它在闲置时占用 1.3 GB 的内存,CPU 使用率为 1%。但是,随着你安装和打开更多应用程序,性能指标可能会上升。

然而,由于预装了许多应用程序和 Xfce 桌面,它的安装需要大约 14 GB 的磁盘空间。另外,正如我之前提到的,整个安装需要 24 GB 的可用磁盘空间。

Voyager Linux 性能

总结

在测评了 Voyager Linux 23.04 之后,我相信它是一个理想的、可以日常使用的非 Snap Ubuntu 变体。如果你不喜欢 Ubuntu GNOME 的默认外观,并且正在寻找具有稳定的 Ubuntu 长期支持/短期基础,且设计吸引人的预配置发行版,那么 Voyager Linux 可能是你的完美选择。

此外,最棒的是在同样的 Ubuntu 基础上还有一个 Xfce 桌面可以选择。试一试吧。

你可以在其 官方网站 下载 Voyager Linux。

(题图:MJ/2deebcdf-7e04-43bc-beaf-7059e80b8057)


via: https://www.debugpoint.com/voyager-linux-review-23-04/

作者:Arindam 选题:lkxed 译者:XiaotingHuang22 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

微软 WSL2 工程师超爱的 Linux 功能

在温哥华举行的 Linux 基金会的开源峰会上,微软的 WSL2 工程团队分享了他们喜欢的 Linux 内核功能。这包括多代 LRU(MGLRU)、用于编译器优化的性能剖析导引优化(PGO)、用于虚拟 GPU 处理的 VirtIO-GPU,暂停到磁盘等。

消息来源:Phoronix
老王点评:不知道微软会不会“借鉴”这些功能到 Windows 中,反正 Linux 从 Windows 中借鉴比较难,微软似乎没有开源操作系统底层技术方面的惯例。

红帽裁掉了 Fedora 项目经理

在这次的红帽裁员中,Fedora 项目经理 Ben Cotton 不幸被裁掉了。他在过去五年中一直担任 Fedora 项目经理。该职位负责协调 Fedora 社区和红帽工程、上游项目、硬件供应商等之间的关系,还负责 Fedora 社区的选举。此外,Cotton 也是提出 CentOS Stream 计划的人之一。Cotton 表示他已经在寻找新的机会,并准备休息一段时间。他说,“我的目标是,在几个月后,没有人会注意到我已经离开了。这是我衡量成功的标准。多年来,我一直在努力将可以自动化的任务自动化。如果 Fedora 脱离了轨道,那么我就失败了。”他表示,没有迹象表明他的角色被特别针对,红帽公司里肯定有一些人继续把 Fedora 看作是具有战略意义的。

消息来源:Phoronix
老王点评:姑且让我们相信这背后不代表红帽公司对 Fedora 的想法发生了变化。那么从职业生涯的角度看,当你把一切都做好自动化了,是不是你就可以很顺滑地被裁掉了?而从公司的角度看,一个岗位如果能不依赖任何特定的人,也不需要专人,那才有保障。所以,如果是你,你会怎么做?

微软云服务会扫描有密码的压缩文件

一位安全专家说,他通过用密码保护的压缩文件向同事发送恶意程序样本,但该压缩文件被微软标记为存在恶意代码,从而阻止了该文件。将文件内容压缩到存档的压缩文件中,长期以来一直是威胁者用来掩盖恶意软件的一种策略。而微软正在尝试绕过压缩文件的密码保护,并在成功后对其进行恶意代码扫描,从而一举击破这一举措。据称,微软会通过邮件正文、文件名等猜测密码。微软没有经过用户允许就解开了用密码保护的压缩文件,而且没有提供绕开的方法,令人感到冒犯。而谷歌表示,他们不会检查带密码的压缩文件。

消息来源:Ars Technica
老王点评:这颇有种被海关将行李箱彻底翻开检查一遍的感觉。难道真的需要用强加密、非对称加密吗?

嗨!昨天我试着写点关于浮点数的东西,我发现自己对这个 64 位浮点数的计算方法很好奇:

>>> 0.1 + 0.2
0.30000000000000004

我意识到我并没有完全理解它是如何计算的。我的意思是,我知道浮点计算是不精确的,你不能精确地用二进制表示 0.1,但是:肯定有一个浮点数比 0.30000000000000004 更接近 0.3!那为什么答案是 0.30000000000000004 呢?

如果你不想阅读一大堆计算过程,那么简短的答案是: 0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 正好位于两个浮点数之间,即 0.299999999999999988897769753748434595763683319091796875 (通常打印为 0.3) 和 0.3000000000000000444089209850062616169452667236328125(通常打印为 0.30000000000000004)。答案是 0.30000000000000004,因为它的尾数是偶数。

浮点加法是如何计算的

以下是浮点加法的简要计算原理:

  • 把它们精确的数字加在一起
  • 将结果四舍五入到最接近的浮点数

让我们用这些规则来计算 0.1 + 0.2。我昨天才刚了解浮点加法的计算原理,所以在这篇文章中我可能犯了一些错误,但最终我得到了期望的答案。

第一步:0.1 和 0.2 到底是多少

首先,让我们用 Python 计算 0.10.2 的 64 位浮点值。

>>> f"{0.1:.80f}"
'0.10000000000000000555111512312578270211815834045410156250000000000000000000000000'
>>> f"{0.2:.80f}"
'0.20000000000000001110223024625156540423631668090820312500000000000000000000000000'

这确实很精确:因为浮点数是二进制的,你也可以使用十进制来精确的表示。但有时你只是需要一大堆数字:)

第二步:相加

接下来,把它们加起来。我们可以将小数部分作为整数加起来得到确切的答案:

>>> 1000000000000000055511151231257827021181583404541015625 + 2000000000000000111022302462515654042363166809082031250
3000000000000000166533453693773481063544750213623046875

所以这两个浮点数的和是 0.3000000000000000166533453693773481063544750213623046875

但这并不是最终答案,因为它不是一个 64 位浮点数。

第三步:查找最接近的浮点数

现在,让我们看看接近 0.3 的浮点数。下面是最接近 0.3 的浮点数(它通常写为 0.3,尽管它不是确切值):

>>> f"{0.3:.80f}"
'0.29999999999999998889776975374843459576368331909179687500000000000000000000000000'

我们可以通过 struct.pack0.3 序列化为 8 字节来计算出它之后的下一个浮点数,加上 1,然后使用 struct.unpack

>>> struct.pack("!d", 0.3)
b'?\xd3333333'
# 手动加 1
>>> next_float = struct.unpack("!d", b'?\xd3333334')[0]
>>> next_float
0.30000000000000004
>>> f"{next_float:.80f}"
'0.30000000000000004440892098500626161694526672363281250000000000000000000000000000'

当然,你也可以用 math.nextafter

>>> math.nextafter(0.3, math.inf)
0.30000000000000004

所以 0.3 附近的两个 64 位浮点数是 0.2999999999999999888977697537484345957636833190917968750.3000000000000000444089209850062616169452667236328125

第四步:找出哪一个最接近

结果证明 0.3000000000000000166533453693773481063544750213623046875 正好在 0.2999999999999999888977697537484345957636833190917968750.3000000000000000444089209850062616169452667236328125 的中间。

你可以通过以下计算看到:

>>> (3000000000000000444089209850062616169452667236328125000 + 2999999999999999888977697537484345957636833190917968750) // 2 == 3000000000000000166533453693773481063544750213623046875
True

所以它们都不是最接近的。

如何知道四舍五入到哪一个?

在浮点数的二进制表示中,有一个数字称为“尾数”。这种情况下(结果正好在两个连续的浮点数之间),它将四舍五入到偶数尾数的那个。

在本例中为 0.300000000000000044408920985006261616945266723632812500

我们之前就见到了这个数字的尾数:

  • 0.30000000000000004 是 struct.unpack('!d', b'?\xd3333334') 的结果
  • 0.3 是 struct.unpack('!d', b'?\xd3333333') 的结果

0.30000000000000004 的大端十六进制表示的最后一位数字是 4,它的尾数是偶数(因为尾数在末尾)。

我们用二进制来算一下

之前我们都是使用十进制来计算的,这样读起来更直观。但是计算机并不会使用十进制,而是用 2 进制,所以我想知道它是如何计算的。

我不认为本文的二进制计算部分特别清晰,但它写出来对我很有帮助。有很多数字,读起来可能很糟糕。

64 位浮点数如何计算:指数和尾数

64 位浮点数由 2 部分整数构成:指数尾数,还有 1 比特 符号位.

以下是指数和尾数对应于实际数字的方程:

例如,如果指数是 1,尾数是 2**51,符号位是正的,那么就可以得到:

它等于 2 * (1 + 0.5),即 3。

步骤 1:获取 0.1 和 0.2 的指数和尾数

我用 Python 编写了一些低效的函数来获取正浮点数的指数和尾数:

def get_exponent(f):
    # 获取前 52 个字节
    bytestring = struct.pack('!d', f)
    return int.from_bytes(bytestring, byteorder='big') >> 52

def get_significand(f):
    # 获取后 52 个字节
    bytestring = struct.pack('!d', f)
    x = int.from_bytes(bytestring, byteorder='big')
    exponent = get_exponent(f)
    return x ^ (exponent << 52)

我忽略了符号位(第一位),因为我们只需要处理 0.1 和 0.2,它们都是正数。

首先,让我们获取 0.1 的指数和尾数。我们需要减去 1023 来得到实际的指数,因为浮点运算就是这么计算的。

>>> get_exponent(0.1) - 1023
-4
>>> get_significand(0.1)
2702159776422298

它们根据 2**指数 + 尾数 / 2**(52 - 指数) 这个公式得到 0.1

下面是 Python 中的计算:

>>> 2**-4 + 2702159776422298 / 2**(52 + 4)
0.1

(你可能会担心这种计算的浮点精度问题,但在本例中,我很确定它没问题。因为根据定义,这些数字没有精度问题 -- 从 2**-4 开始的浮点数以 1/2**(52 + 4) 步长递增。)

0.2 也一样:

>>> get_exponent(0.2) - 1023
-3
>>> get_significand(0.2)
2702159776422298

它们共同工作得到 0.2:

>>> 2**-3 + 2702159776422298 / 2**(52 + 3)
0.2

(顺便说一下,0.1 和 0.2 具有相同的尾数并不是巧合 —— 因为 x2*x 总是有相同的尾数。)

步骤 2:重新计算 0.1 以获得更大的指数

0.2 的指数比 0.1 大 -- -3 大于 -4。

所以我们需要重新计算:

2**-4 + 2702159776422298 / 2**(52 + 4)

等于 X / 2**(52 + 3)

如果我们解出 2**-4 + 2702159776422298 / 2**(52 + 4) = X / 2**(52 + 3),我们能得到:

X = 2**51 + 2702159776422298 / 2

在 Python 中,我们很容易得到:

>>> 2**51 + 2702159776422298 //2
3602879701896397

步骤 3:添加符号位

现在我们试着做加法:

2**-3 + 2702159776422298 / 2**(52 + 3) + 3602879701896397 / 2**(52 + 3)

我们需要将 27021597764222983602879701896397 相加:

>>> 2702159776422298  + 3602879701896397
6305039478318695

棒。但是 63050394783186952**52-1(尾数的最大值)大,问题来了:

>>> 6305039478318695 > 2**52
True

第四步:增加指数

目前结果是:

2**-3 + 6305039478318695 / 2**(52 + 3)

首先,它减去 2**52:

2**-2 + 1801439850948199 / 2**(52 + 3)

完美,但最后的 2**(52 + 3) 需要改为 2**(52 + 2)

我们需要将 1801439850948199 除以 2。这就是难题的地方 -- 1801439850948199 是一个奇数!

>>> 1801439850948199  / 2
900719925474099.5

它正好在两个整数之间,所以我们四舍五入到最接近它的偶数(这是浮点运算规范要求的),所以最终的浮点结果是:

>>> 2**-2 + 900719925474100 / 2**(52 + 2)
0.30000000000000004

它就是我们预期的结果:

>>> 0.1 + 0.2
0.30000000000000004

在硬件中它可能并不是这样工作的

在硬件中做浮点数加法,以上操作方式可能并不完全一模一样(例如,它并不是求解 “X”),我相信有很多有效的技巧,但我认为思想是类似的。

打印浮点数是非常奇怪的

我们之前说过,浮点数 0.3 不等于 0.3。它实际上是:

>>> f"{0.3:.80f}"
'0.29999999999999998889776975374843459576368331909179687500000000000000000000000000'

但是当你打印它时,为什么会显示 0.3

计算机实际上并没有打印出数字的精确值,而是打印出了最短的十进制数 d,其中 f 是最接近 d 的浮点数。

事实证明,有效做到这一点很不简单,有很多关于它的学术论文,比如 快速且准确地打印浮点数如何准确打印浮点数 等。

如果计算机打印出浮点数的精确值,会不会更直观一些?

四舍五入到一个干净的十进制值很好,但在某种程度上,我觉得如果计算机只打印一个浮点数的精确值可能会更直观 -- 当你得到一个奇怪的结果时,它可能会让你看起来不那么惊讶。

对我来说,0.1000000000000000055511151231257827021181583404541015625 + 0.200000000000000011102230246251565404236316680908203125 = 0.30000000000000004440892098500626161694526672363281250.1 + 0.2 = 0.30000000000000000004 惊讶少一点。

这也许是一个坏主意,因为它肯定会占用大量的屏幕空间。

PHP 快速说明

有人在评论中指出在 PHP 中 <?php echo (0.1 + 0.2 );?> 会输出 0.3,这是否说明在 PHP 中浮点运算不一样?

非也 —— 我在 这里 运行:

<?php echo (0.1 + 0.2 )- 0.3);?>,得到了与 Python 完全相同的答案:5.5511151231258E-17。因此,浮点运算的基本原理是一样的。

我认为在 PHP 中 0.1 + 0.2 输出 0.3 的原因是 PHP 显示浮点数的算法没有 Python 精确 —— 即使这个数字不是最接近 0.3 的浮点数,它也会显示 0.3

总结

我有点怀疑是否有人能耐心完成以上所有些算术,但它写出来对我很有帮助,所以我还是发表了这篇文章,希望它能有所帮助。

(题图:MJ/53e9a241-14c6-4dc7-87d0-f9801cd2d7ab)


via: https://jvns.ca/blog/2023/02/08/why-does-0-1-plus-0-2-equal-0-30000000000000004/

作者:Julia Evans 选题:lkxed 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在开发初期只对单个元素进行编码和测试,之后再拓展到多个元素上。

 title=

上一篇文章 中我已经解释了为什么把所有编程问题当作一群丧尸一次性处理是错误的。我也解释了 ZOMBIES 方法中的第一条:最简场景。本文中我将进一步介绍接下来的两条:单元素场景和多元素场景。

ZOMBIES 表示以下首字母缩写:

  • Z – 最简场景(Zero)
  • O – 单元素场景(One)
  • M – 多元素场景(Many or more complex)
  • B – 边界行为(Boundary behaviors)
  • I – 接口定义(Interface definition)
  • E – 处理特殊行为(Exercise exceptional behavior)
  • S – 简单场景用简单的解决方案(Simple scenarios, simple solutions)

在上一篇文章中,通过应用了最简场景,你在代码里构建了一条最简可行通路。这个代码里没有任何业务处理逻辑。现在是时候向系统中添加一个元素了。

最简场景表示系统中什么也没有,这是一个空的用例,我们什么也不用关心。单元素场景代表我们有一个元素需要关心考虑。这个单一元素可能是集合中的一个元素、一个访问着或者一个需要处理的事件。

对于多元素场景,我们需要处理更复杂的情况,比如两个或更多的集合元素或事件。

单元素场景

在上一篇文章的代码基础上,向虚拟购物筐里添加一些商品。首先,写一个伪测试:

[Fact]
public void Add1ItemBasketHas1Item() {
        var expectedNoOfItems = 1;
        var actualNoOfItems = 0;
        Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

不出所料,这个测试失败了,因为硬编码了一个错误的值:

Starting test execution, please wait...

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.57] tests.UnitTest1.NewlyCreatedBasketHas0Items [FAIL]
  X tests.UnitTest1.NewlyCreatedBasketHas0Items [4ms]
  Error Message:
   Assert.Equal() Failure
Expected: 0
Actual: 1
[...]

现在是时候停止伪造了。现在你已经用 ArrayList 实现了购物筐。那么应该怎么实现商品呢?

简洁性应该一直是你的指导原则。在不了解商品的太多信息的情况下,你可以先用另一个集合来实现它。这个表示商品的集合应该包含些什么呢?由于你多半会关心计算购物筐中的商品总价,所以对商品的表示至少需要包含价格(可以是任意货币,为简单起见,不妨假设是人民币)。

(我们需要)一个简单的集合类型,它包含一个商品 ID(可以在系统中的其它地方使用 ID 来指向该商品)和这个商品的价格。

键值对类型的数据结构可以很容易满足这个需求。在 C# 中最先被想到的数据结构就是 Hashtable

在购物应用的代码中给 IShoppingAPI 增加一个新功能:

int AddItem(Hashtable item);

这个新功能以一个用 Hashtable 表示的商品为输入,返回购物筐中的商品数量。

将测试代码中硬编码的值提替换为对接口的调用:

[Fact]
public void Add1ItemBasketHas1Item() {            
    var expectedNoOfItems = 1;
    Hashtable item = [new][3] Hashtable();
    var actualNoOfItems = shoppingAPI.AddItem(item);
    Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

在上面的代码中实例化了一个 Hashtable 并命名为 item,然后调用购物接口中的 AddItem(item) 方法,该方法会返回购物筐中实际的商品数量。

转到 ShoppingAPI 类中,实现这个方法:

public int AddItem(Hashtable item) {
    return 0;
}

这里再次通过写假代码来检验测试的效果(测试是业务代码的第一个调用者)。如果测试失败,将硬编码值换成实际的代码:

public int AddItem(Hashtable item) {
    basket.Add(item);
    return basket.Count;
}

在上面的代码中,向购物筐里添加了一件商品,然后返回购物筐中的商品数量:

Test Run Successful.
Total tests: 2
     Passed: 2
 Total time: 1.0633 Seconds

到目前为止,你通过了两个测试,同时也基本里解了 ZOMBIES 方法中的最简场景和单元素场景两部分。

反思总结

回顾前面所做的工作,你会发现通过将注意力集中到处理最简场景和单元素场景上,你在构建接口的同时也定义了一些业务逻辑边界!这不是很棒吗?现在你已经部分地实现了最关键的抽象逻辑,并且能够处理什么也没有和只有一个元素的的情况。因为你正在构建的是一个电子交易 API,所以你不能对顾客的购物行为预设其它限制。总而言之,虚拟购物筐应该是无限大的。

ZOMBIES 提供的逐步优化思路的另一个重要方面(虽然不是很明显)是从大概思路到具体实现的阻力。你也许已经注意到了,要具体实现某个东西总是困难重重。倒不如先用硬编码值来构造一个伪实现。只有看到接口与测试之间以一种合理的方式交互之后,你才会愿意开始完善实现代码。

即便如此,你也应该采用简单直接的代码结构,尽可能避免条件逻辑分支。

多元素场景

通过定义顾客向购物筐里添加两件商品时的期望来拓展应用程序。首先构造一个伪测试。它的期望值为 2,但是现在将实际值硬编码为 0,强制让测试失败:

[Fact]
public void Add2ItemsBasketHas2Items() {
        var expectedNoOfItems = 2;
        var actualNoOfItems = 0;
        Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

执行测试,前两个测试用例通过了(针对最简场景和单元素场景的测试),而硬编码的测试不出所料地失败了:

A total of 1 test files matched the specified pattern.
[xUnit.net 00:00:00.57] tests.UnitTest1.Add2ItemsBasketHas2Items [FAIL]
  X tests.UnitTest1.Add2ItemsBasketHas2Items [2ms]
  Error Message:
   Assert.Equal() Failure
Expected: 2
Actual: 0

Test Run Failed.
Tatal tests: 3
     Passed: 2
     Failed: 1

将硬编码值替换为实际的代码调用:

[Fact]
public void Add2ItemsBasketHas2Items() {
        var expectedNoOfItems = 2;
        Hashtable item = [new][3] Hashtable();
        shoppingAPI.AddItem(item);
        var actualNoOfItems = shoppingAPI.AddItem(item);
        Assert.Equal(expectedNoOfItems, actualNoOfItems);
}

在这个测试中,你向购物筐中添加了两件商品(实际上是将同一件商品添加了两次),然后比较期望的商品数量和第二次添加商品后调用 shoppingAPI 返回的商品数量是否相等。

现在所有测试都能够通过!

敬请期待

现在你已经了解了最简场景、单元素场景和多元素场景。我将下一篇文章中介绍边界行为和接口定义。敬请期待!

(题图:MJ/e4679f1f-311a-4a41-80e8-8d2834b956f2)


via: https://opensource.com/article/21/2/build-expand-software

作者:Alex Bunardzic 选题:lujun9972 译者:toknow-gh 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

某种程度上亚马逊 OpenSearch 成功了

2021 年,开发 Elasticsearch 和 Kibana 的 Elastic 公司宣布更改许可证,此举旨在禁止云服务商如 AWS 使用它的软件作为一种服务提供给客户,但这也意味着这两个软件不再是开源软件。发生此事的原因是,Elastic 认为云服务商只使用开源软件,而不向开源软件做贡献。AWS 随后宣布创建 ElasticSearch 开源分支 OpenSearch,承诺会向其提交贡献。如今,OpenSearch 下载量突破 1 亿,包括 AWS 员工在内的 496 名贡献者递交了 8760 个拉取请求,Adobe 也决定在其套件中用 OpenSearch 取代 Elasticsearch,它甚至还进入了 DB-Engines 数据库流行度排名前五十。

消息来源:Info World
老王点评:我是没想到 OpenSearch 能成功。当时在我看来,以 AWS 对开源主要是利用的态度来看,这必然是一个失败的产品。但是,没想到 AWS 在悄悄变化。之前,我们报道过,AWS 已经是 Postgresql 前四的贡献者。所以,这不是 AWS 的胜利,而是开源的胜利。当然,另一面,Elastic 的境况似乎也不错,虽然它的许可证导致它的产品不再是符合定义的“开源”产品,但是其实还是公开源代码的。

KDE Plasma 6 修改默认设置,默认双击打开

KDE 开发者发布的一篇博文描述了为 Plasma 桌面环境所做的工作。其中一个重点是更好的默认设置,以改善开箱即用的用户体验。博文中提到,Plasma 6 将默认用双击而不是单击来打开文件和文件夹,尽管 Linux 用户已经习惯了单击,但这对从 Windows 迁移过来的用户更友好;Wayland 成为 Plasma 6 的默认会话类型;默认使用缩略图网格任务切换器等等。此外,KDE 开发者还吐槽了微软在 Windows 11 中公然抄袭了 Plasma 的浮动面板,但是,人们把 Plasma 看作是 Windows 的廉价克隆。

消息来源:Slashdot
老王点评:对于 Linux 上的桌面环境,就有这样的两难处境:像 Windows 吧,被人说仿品;不像吧,被人说用户体验糟糕。先提出创新吧,被嫌弃,Windows 用了,反而成了抄袭者。唉,真是难啊。

人工智能可以比医生早 3 年预测出胰腺癌

根据发表在《自然》杂志上的研究,人工智能比人类医生做出同样的诊断要早三年时间。胰腺癌是致命的;五年的存活率平均为 12%。癌症在人体中逐渐发展,往往经过多年,而且相当缓慢,直到疾病发生。人工智能系统试图从人体中可能与这种逐渐变化有关的迹象中学习。研究人员在数百万份医疗记录上训练了人工智能算法。该研究仍处于早期阶段,而且该软件还不能用于进行筛查。在进行试验之前,还需要进行改进,人工智能在未来可能会成为一种有价值的筛查工具。

消息来源:The Register
老王点评:人工智能不只是一个对话机器人,它真正改变世界的地方是它能在浩如烟海的数据中找到人类发现不了的规律。十来年前,我曾经做过根据先验数据给出健康和疾病预测评估的工作,要是有现在的人工智能的研究,可能会有更有价值的评估结果吧。

在本指南中,你将了解如何在 Ubuntu/Debian Linux 发行版中为 apt 命令设置代理。

代理服务器是位于请求资源的客户端系统或最终用户与资源本身之间的中间服务器。在大多数情况下,代理服务器充当最终用户和互联网之间的网关。

对于组织和企业环境,代理服务器提供了许多好处。它通过阻止被认为会影响员工工作效率的网站来控制互联网的使用。它还通过数据加密增强隐私并提高组织的安全性。

有几种方法可以为 apt 命令设置代理,让我们直接进入。

注意:为了演示,我们将使用 Ubuntu 22.04。

使用代理文件为 APT 配置代理

apt 命令配置代理的最简单方法是创建一个 proxy.conf 文件,如下:

$ sudo vi /etc/apt/apt.conf.d/proxy.conf

对于没有用户名和密码的代理服务器,添加以下条目,如下:

对于 HTTP 代理,添加以下条目:

Acquire::http::Proxy "http://proxy-IP-address:proxyport/";

对 HTTPS 代理执行相同的操作:

Acquire::https::Proxy "http://proxy-IP-address:proxyport/";

例子:

$ cat  /etc/apt/apt.conf.d/proxy.conf
Acquire::http::Proxy "http://192.168.56.102:3128/";
Acquire::https::Proxy "http://192.168.56.102:3128/";

如果你的代理服务器需要用户名和密码详细信息,请按以下方式添加:

Acquire::http::Proxy "http://username:password@proxy-IP-address:proxyport";
Acquire::https::Proxy "http://username:password@proxy-IP-address:proxyport";

例子:

$ cat  /etc/apt/apt.conf.d/proxy.conf
Acquire::http::Proxy "http://init@PassW0rd321#@192.168.56.102:3128/";
Acquire::https::Proxy "http://init@PassW0rd321#@192.168.56.102:3128/";

完成后,保存更改并退出配置文件。代理设置将在你下次运行 APT 包管理器时生效。

例如,你可以更新本地包索引,然后安装 net-tools 包:

$ sudo apt update
$ sudo apt install net-tools -y

验证代理服务器日志以确认 apt 命令正在使用代理服务器下载包。在代理服务器运行时:

# tail -f /var/log/squid/access.log  | grep -i 192.168.56.240

这里 192.168.56.240 是我们 Ubuntu 机器的 IP 地址。

完美,上面的输出确认我们的 Ubuntu 系统的 apt 命令正在通过代理服务器(192.168.56.102)下载包。

另一种指定代理详细信息的方法

除了第一种方法,你还可以用更简单的方式指定代理详细信息。再次创建一个 proxy.conf 文件,如下所示。

$ sudo vi /etc/apt/apt.conf.d/proxy.conf

对于没有用户名和密码的代理服务器,如图所示进行定义。

Acquire {
  http::Proxy "http://proxy-IP-address:proxyport/";
  https::Proxy "http://proxy-IP-address:proxyport/";
}

示例文件如下所示:

$ sudo vi /etc/apt/apt.conf.d/proxy.conf

对于具有用户名和登录详细信息的代理服务器:

Acquire {
   http::Proxy "http://username:password@proxy-IP-address:proxyport/";
   https::Proxy "http://username:password@proxy-IP-address:proxyport/";
}

保存更改并退出配置文件。提醒一下,当你开始使用 APT 包管理器,这些设置就会立即生效。

总结

本指南到此结束。在本教程中,我们演示了如何为 Debian/Ubuntu Linux 发行版中使用的 APT 包管理器配置代理设置。本文就到这里了。

(题图:MJ/dfb4d5a0-9150-47bd-9f54-c120ddd77046)


via: https://www.linuxtechi.com/set-proxy-settings-for-apt-command/

作者:James Kiarie 选题:lkxed 译者:geekpi 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出