Go-知识测试-模糊测试

news2024/9/25 3:19:33

Go-知识测试-模糊测试

  • 1. 定义
  • 2. 例子
  • 3. 数据结构
  • 4. tesing.F.Add
  • 5. 模糊测试的执行
  • 6. testing.InternalFuzzTarget
  • 7. testing.runFuzzing
  • 8. testing.fRunner
  • 9. FuzzXyz
  • 10. RunFuzzWorker
  • 11. CoordinateFuzzing
  • 12. 总结

建议先看:https://blog.csdn.net/a18792721831/article/details/140062769

Go-知识测试-工作机制

1. 定义

模糊测试(Fuzzing)是一种通过构造随机数据对代码进行测试的测试方法,相比于单元测试,
它能提供更为全面的测试覆盖,从而找出代码中的潜在漏洞。
从1.18开始,Go开始正式支持模糊测试。
模糊测试要保证测试文件以_test.go结尾。
测试方法必须以FuzzXxx开头。
模糊测试方法必须以*testing.F作为参数。

2. 例子

假设有个函数,根据输入内容,将输入进行翻转然后在和输入拼接,从而返回一个回文串(不一定是严格意义下的回文串)
函数如下:

func PalindromeStr(in string) string {
	b := []byte(in)
	for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {
		b[i], b[j] = b[j], b[i]
	}
	return in + string(b)
}

接着使用单元测试

func TestPalindromeStr(t *testing.T) {
	testCase := []struct{ in, out string }{
		{"abc", "abccba"},
		{"abcdef", "abcdeffedcba"},
		{"abcdefg", "abcdefggfedcba"},
		{" ", "  "},
	}
	for _, c := range testCase {
		o := PalindromeStr(c.in)
		if o != c.out {
			t.Error("Not equal", c.out, "got:", o)
		}
	}
}

使用go test -v 执行示例测试,-v 表示控制台输出结果
在这里插入图片描述

接着使用模糊测试

func FuzzPalindromeStr(f *testing.F) {
	testCase := []string{"abc", "def", " ", "a", "aaa", "aaaaaaaaaaaaaaaaaaaa"}
    for _, c := range testCase {
        f.Add(c) // 输入测试种子
    }
    f.Fuzz(func(t *testing.T, a string) {
        b := PalindromeStr(a)
		// 返回结果进行判断,回文串的规则就是第一个字符和最后一个字符相同,依次类推
        for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {
            if b[i] != b[j] {
                t.Error("Not palindrome")
            }
        }
    })
}

使用go test -fuzz=Fuzz -fuzztime=100s启动模糊测试,-fuzz表示执行模糊测试,-fuzztime表示持续时间
在这里插入图片描述

发现执行了100s,也没法问题。
那么我们就自动构造一个错误,如果是utf-8字符,返回回文串,否则返回输入内容,模拟异常逻辑:

func PalindromeStr(in string) string {
	b := []byte(in)
	if !utf8.Valid(b) {
		return in
	}
	for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {
		b[i], b[j] = b[j], b[i]
	}
	return in + string(b)
}

因为单元测试中没有中文字符,所以单元测试通过,但是模糊测试呢:
在这里插入图片描述

报错了,同时testdata目录中有相应的输入和输出
在这里插入图片描述

非utf8字符串,触发了错误逻辑

3. 数据结构

由于模糊测试可以覆盖人类经常忽略的边界用例,因此模糊测试对于发现安全漏洞特别有价值。
模糊测试的结构如下:
在这里插入图片描述

看起来很像单元测试的扩展。
一个模糊测试可以分为两部分,一是通过 f.Add 添加随机种子,二是通过 f.Fuzz 函数开始随机测试。标记测试结果的方法与之前的单元测试是通用的。
模糊测试的testing.F结构:
go在1.18中,在testing的包中增加了fuzz.go文件,支持模糊测试:

type F struct {
	common // 通用测试结构,更多见 https://blog.csdn.net/a18792721831/article/details/140062769
	fuzzContext *fuzzContext // 与 testContext 类似,用于控制执行
	testContext *testContext
	inFuzzFn bool // 标记 fuzz 是否在运行中
	corpus []corpusEntry // 种子,语料库
	result     fuzzResult // 模糊测试结果
	fuzzCalled bool // 是否启动
}

通用测试结构 common 提供了诸如标记测试结果的能力,而增加的 corpus 则用于保存通过 f.Add 添加的种子和测试过程中生成的随机输入。
每次执行 f.Add 都会生成一个 corpusEntry 对象,然后加入 corpus 语料库中。
corpusEntry 结构用于保存待测函数的所有输入:

type corpusEntry = struct {
	Parent     string
	Path       string
	Data       []byte
	Values     []any // Values 要与待测函数索旭耀的参数完全一致
	Generation int
	IsSeed     bool
}

f.Add 每次添加的种子个数需要与待测函数所需要的参数完全一致,因为测试执行时,每次取出一组种子作为函数的入参。

4. tesing.F.Add

func (f *F) Add(args ...any) {
    // 将输入的参数加入到数组中
	var values []any
	for i := range args {
	    // 模糊测试只能支持基本数据类型,对于复杂类型是不支持的
		if t := reflect.TypeOf(args[i]); !supportedTypes[t] {
			panic(fmt.Sprintf("testing: unsupported type to Add %v", t))
		}
		values = append(values, args[i])
	}
	f.corpus = append(f.corpus, corpusEntry{Values: values, IsSeed: true, Path: fmt.Sprintf("seed#%d", len(f.corpus))})
}

支持模糊测试的参数类型:

var supportedTypes = map[reflect.Type]bool{
	reflect.TypeOf(([]byte)("")):  true,
	reflect.TypeOf((string)("")):  true,
	reflect.TypeOf((bool)(false)): true,
	reflect.TypeOf((byte)(0)):     true,
	reflect.TypeOf((rune)(0)):     true,
	reflect.TypeOf((float32)(0)):  true,
	reflect.TypeOf((float64)(0)):  true,
	reflect.TypeOf((int)(0)):      true,
	reflect.TypeOf((int8)(0)):     true,
	reflect.TypeOf((int16)(0)):    true,
	reflect.TypeOf((int32)(0)):    true,
	reflect.TypeOf((int64)(0)):    true,
	reflect.TypeOf((uint)(0)):     true,
	reflect.TypeOf((uint8)(0)):    true,
	reflect.TypeOf((uint16)(0)):   true,
	reflect.TypeOf((uint32)(0)):   true,
	reflect.TypeOf((uint64)(0)):   true,
}

除了这些之外的类型都不支持。

5. 模糊测试的执行

src/tesing/fuzz.goinitFuzzFlags中定义了模糊测试的参数:

func initFuzzFlags() {
	matchFuzz = flag.String("test.fuzz", "", "run the fuzz test matching `regexp`")
	flag.Var(&fuzzDuration, "test.fuzztime", "time to spend fuzzing; default is to run indefinitely")
	flag.Var(&minimizeDuration, "test.fuzzminimizetime", "time to spend minimizing a value after finding a failing input")

	fuzzCacheDir = flag.String("test.fuzzcachedir", "", "directory where interesting fuzzing inputs are stored (for use only by cmd/go)")
	isFuzzWorker = flag.Bool("test.fuzzworker", false, "coordinate with the parent process to fuzz random values (for use only by cmd/go)")
}

首先使用-fuzz=reg触发模糊测试,-fuzztime=30s指定模糊测试持续的时间,如果不指定,则一直运行。
-fuzzminimizetime最小失败时间,默认一分钟,-fuzzcachedir缓存目录,默认是命令执行目录,fuzzworker工作目录,默认是命令执行目录。

6. testing.InternalFuzzTarget

testing.M中,对于单元测试,示例测试和性能测试,都有一个内部类型用于存储编译生成的执行参数。模糊测试也有:
在这里插入图片描述

在1.18中三种内部类型增加成4种了。
在编译的时候,load操作也增加了 Fuzz开头的模糊测试函数
在这里插入图片描述

在渲染测试的main入口中,也增加了模糊测试的模板
在这里插入图片描述

在testing.M.Run中,增加了模糊测试的支持
在这里插入图片描述

InternalFuzzTarget的结构:

type InternalFuzzTarget struct {
	Name string
	Fn   func(f *F)
}

很简单,和单元测试等的结构非常类似,name和对应的func,func 的参数是 *testing.F

7. testing.runFuzzing

在runFuzzing中首先对全部的模糊测试进行匹配,找到本次期望执行的模糊测试case
在这里插入图片描述

接着构造testing.F对象,调用testing.fRunner执行case
在这里插入图片描述

8. testing.fRunner

在testing.fRunner中启动执行,类似于单元测试的 testing.tRunner。
在这里插入图片描述

性能测试是 testing.runN
示例测试是 testing.runExample
单元测试是 testing.tRunner

第一个defer函数主要处理这几个事情:失败后资源清理,保证测试报告完成,失败退出,等待子测试完成,成功输出报告。
第二个defer函数是等待所有的子测试完成后,发送信号,表示子测试结束。

9. FuzzXyz

接着回到模糊测试中:

func FuzzPalindromeStr(f *testing.F) {
	testCase := []string{"abc", "def", " ", "a", "aaa", "你好"}
	for _, c := range testCase {
		f.Add(c) // 输入测试种子
	}
	f.Fuzz(func(t *testing.T, a string) {
		b := PalindromeStr(a)
		// 返回结果进行判断,回文串的规则就是第一个字符和最后一个字符相同,依次类推
		for i, j := 0, len(b)-1; i < len(b)/2; i, j = i+1, j-1 {
			if b[i] != b[j] {
				t.Error("Not palindrome")
			}
		}
	})
}

模糊测试可以认为是两部分,第一部分是输入测试种子,第二部分是判决模糊的参数执行是否成功。
在testing.F.Add中,将参数种子放到了testing.F.corpus里面,并且要求输入的种子参数的数量,每次Add的时候,必须和被测试方法的入参一致。
在第二部分的Fuzz中,首先对入参进行了校验:
在这里插入图片描述

入参是一个func类型的参数,并且第一个参数是*testing.T的参数,后面是可变参数。
第一个*testing.T主要是复用了单元测试的测试管理能力,比如报告输出,成功失败的标记等等。
后面的可变参数则是被模糊测试的函数入参列表。
接着对可变参数列表进行类型判断,只有基本类型才能模糊测试,如果入参中存在复杂类型,那么是无法模糊测试的。
在这里插入图片描述

接下来就是模糊的核心逻辑了,如何根据输入的参数种子,派生更多的入参用例:
在这里插入图片描述

模糊测试的goroutine分为三种
在这里插入图片描述

这三种的含义先存疑。
在CheckCorpus中,对入参种子和可变参数进行校验,确保种子数组中每一组都符合要求。
在ReadCorpus中,则是随机取出本次执行的参数,如果是指定fuzz的目录和id,那么会使用指定的目录下的指定参数去执行
在这里插入图片描述

ReadCorpus调用了internal的fuzz实现
在这里插入图片描述

在ReadCorpus中调用了readCorpusData
在这里插入图片描述

不过上面都是执行特定的模糊case 。
在前面已知模糊测试的goroutine中有三种:

const (
	seedCorpusOnly fuzzMode = iota
	fuzzCoordinator
	fuzzWorker
)

第一种 seedCorpusOnly 是 testing.runFuzzTests 中创建的,由testing.M调用
在这里插入图片描述

第二种 fuzzCoordinator 是 默认的,如果执行的go命令中没有指定 test.fuzzworker , 默认是 false
在 testing.runFuzzing 中创建的
在这里插入图片描述

第三种 fuzzWorker 是由 命令行参数指定的。

在这里插入图片描述

根据这里的逻辑,基本上可以看出,seedCorpusOnly 是读取指定模糊case, fuzzCoordinator是生成模糊case,fuzzWorker是执行case。
在这里插入图片描述

接着创建一个 testing.T 的对象,然后调用 testing.tRunner 执行case 。
在这里插入图片描述

testing.tRunner执行case的参数是 corpusEntry 类型的输入。

也就是说,对于模糊测试,会先直接调用测试种子执行,然后会根据执行情况,在进行随机参数。

如果是 fuzzCoordinator 类型的,那么执行 CoordinateFuzzing
在这里插入图片描述

如果是 fuzzWorker ,执行 RunFuzzWorker
在这里插入图片描述

如果是 seedCorpusOnly ,执行 run func,相当于直接用测试种子运行
在这里插入图片描述

在 fuzzWorker中,对于输出做了重定向。

10. RunFuzzWorker

RunFuzzWorker方法是在internal中实现的
在这里插入图片描述

如果一个case经过了10还没有被执行,就认为是饿死了
在serve方法中调用了workerServer.Fuzz 方法
在这里插入图片描述

并且是持续性调用的
在workerServer.fuzz中进行模糊测试
在workerServer.fuzz中,第一次调用直接使用种子
在这里插入图片描述

接着就是持续性测试了
在这里插入图片描述

在 mutator.mutate 中根据种子进行随机
在这里插入图片描述

会对一次随机的多个参数,随机选择一个参数,然后对这个参数进行随机
比如对于整型,会随机加或者减一个数
在这里插入图片描述

对于字符串,对字节码随机加减
在这里插入图片描述

也就是说,如果你的种子里面有中文,才会随机中文。

contains
accepts
calls
calls
passes
returns
TestDeps
RunFuzzWorker
fn
workerServer.fuzz
mutator.mutate
fuzz.CorpusEntry
error

11. CoordinateFuzzing

CoordinateFuzzing方法在internal中实现的
在这里插入图片描述

首先会对并发数,缓存目录,日志等进行初始化
在这里插入图片描述

根据并发数,创建多个 worker 执行模糊测试
在这里插入图片描述

在coordinate中也是持续测试
在这里插入图片描述

如果没有启动,那么就调用启动初始化等操作,如果收到了退出信号,那么就退出
如果随机输入已经生成,那么就使用随机输入调用
在这里插入图片描述

接着是for-select进行持续性测试,除非模糊测试失败,或者执行模糊测试的时候,有设置超时时间,或者主动退出等
在这里插入图片描述

在workerClient.fuzz中执行
在这里插入图片描述

也是调用 mutator.mutate 进行随机
在这里插入图片描述

同时,在调用FuzzXyz后,会记录case的执行情况,用于分析执行的覆盖率等等
在这里插入图片描述

12. 总结

Go 1.18 的 Fuzz 测试使用了一种称为 “coverage-guided fuzzing” 的技术来生成随机输入。这种技术的基本思想是通过监视被测试代码的覆盖率来引导输入的生成。

具体来说,Fuzz 测试首先使用你提供的种子值(seed values)来运行测试。然后,它会监视这些测试运行过程中哪些代码被执行了,以及输入值如何影响代码的执行路径。

接着,Fuzz 测试会尝试修改种子值或者组合种子值,生成新的输入,以尝试覆盖更多的代码路径。例如,如果你的种子值是字符串,Fuzz 测试可能会改变字符串的长度,添加、删除或修改字符,等等。

如果新的输入导致了更多的代码被执行,或者触发了新的代码路径,那么这个输入就会被保存下来,用作后续测试的种子值。这样,Fuzz 测试就可以逐渐 “学习” 如何生成能够触发更多代码路径的输入。

这种方法可以有效地发现一些难以预见的边界情况,特别是那些可能导致程序崩溃或者行为异常的情况。

需要注意的是,虽然 Fuzz 测试可以自动生成大量的输入,但是它并不能保证完全覆盖所有可能的输入。因此,你仍然需要编写单元测试和集成测试,以确保你的代码在预期的输入下能够正确工作。

Coverage-Guided Fuzzing 相关论文和链接

Coverage-guided fuzzing 是一种基于代码覆盖率的模糊测试技术,通过生成输入数据并监控代码覆盖率来发现潜在的错误和漏洞。这种方法的核心思想是通过最大化代码覆盖率来提高测试的有效性。

  1. “American Fuzzy Lop (AFL)”
    AFL 是一种流行的 coverage-guided fuzzing 工具,由 Michał Zalewski 开发。虽然 AFL 本身不是一篇论文,但它的设计和实现对该领域有着重要影响。
  • 链接: AFL GitHub Repository
  1. “Fuzzing: Brute Force Vulnerability Discovery”
    这篇论文由 Michael Sutton, Adam Greene, 和 Pedram Amini 撰写,详细介绍了模糊测试的基本概念和技术,包括 coverage-guided fuzzing。
  • 链接: Fuzzing: Brute Force Vulnerability Discovery
  1. “Coverage-based Greybox Fuzzing as Markov Chain”
    这篇论文由 Marcel Böhme, Van-Thuan Pham, 和 Abhik Roychoudhury 撰写,提出了一种基于覆盖率的灰盒模糊测试方法,并将其建模为马尔可夫链。
  • 链接: Coverage-based Greybox Fuzzing as Markov Chain
  1. “AFLFast: A Framework for Extremely Fast Fuzzing”
    这篇论文由 Marcel Böhme, Van-Thuan Pham, Manh-Dung Nguyen, 和 Abhik Roychoudhury 撰写,介绍了 AFLFast,这是一种改进的 AFL 版本,通过优化输入生成策略来提高模糊测试的效率。
  • 链接: AFLFast: A Framework for Extremely Fast Fuzzing
  1. “LibFuzzer: A Library for Coverage-Guided Fuzz Testing”
    LibFuzzer 是 LLVM 项目的一部分,提供了一个用于覆盖率引导模糊测试的库。虽然没有正式的论文,但其设计和实现文档非常详细。
  • 链接: LibFuzzer Documentation
  1. “Fuzzing with Code Fragments”
    这篇论文由 Patrice Godefroid, Hila Peleg, 和 Rishabh Singh 撰写,提出了一种基于代码片段的模糊测试方法,通过组合代码片段来生成新的测试输入。
  • 链接: Fuzzing with Code Fragments
  1. “Evaluating Fuzz Testing”
    这篇论文由 Marcel Böhme, Van-Thuan Pham, Manh-Dung Nguyen, 和 Abhik Roychoudhury 撰写,评估了不同模糊测试工具和技术的有效性,包括 coverage-guided fuzzing。
  • 链接: Evaluating Fuzz Testing
  1. “Fuzzing: Art, Science, and Engineering”
    这篇论文由 Patrice Godefroid 撰写,全面介绍了模糊测试的艺术、科学和工程,包括 coverage-guided fuzzing 的技术细节和应用。
  • 链接: Fuzzing: Art, Science, and Engineering

这些论文和资源提供了关于 coverage-guided fuzzing 的深入理解和最新研究成果。通过阅读这些文献,你可以更好地理解这种技术的原理、实现和应用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1920666.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

GitHub连接超时问题 Recv failure: Connection was reset

用手机热点WIF拉取git项目的时候&#xff0c;遇到Recv failure: Connection was reset问题。 解决办法 一、手动开启本地代理 二、在终端&#xff08;cmd&#xff09;输入命令 git config --global http.proxy http://127.0.0.1:7890 git config --global https.proxy https:…

QT实现自定义带有提示信息的透明环形进度条

1. 概述 做界面开发的童鞋可能都会遇到这样的需求&#xff0c;就是有一些界面点击了之后比较耗时的操作&#xff0c;需要界面给出一个环形进度条的进度反馈信息. 如何来实现这样的需求呢&#xff0c;话不多说&#xff0c;上效果 透明进度条 2. 代码实现 waitfeedbackprogressba…

2006-2021年 291个地级市资源错配指数、劳动和资本相对扭曲指数do文件和结果

资源错配指数&#xff1a;衡量生产要素配置效率的关键指标 资源错配指数&#xff08;Misallocation Index&#xff09;是一个衡量资源配置效率的指标&#xff0c;它反映了生产要素是否得到了合理配置&#xff0c;以及是否达到了生产效率的最优状态。一个较高的资源错配指数意味…

three-tile: 一个开源的轻量级三维瓦片库

three-tile 介绍 three-tile 是一个开源的轻量级三维瓦片库&#xff0c;它基于threejs使用typescript开发&#xff0c;提供一个三维地形模型&#xff0c;能轻松给你的应用增加三维瓦片地图。 https://blog.csdn.net/HZGJF/article/details/140280844 源码&#xff1a;https:/…

malloc与free函数的用法(精简全面 · 一看即懂)

前言&#xff1a;Hello大家好&#x1f618;&#xff0c;我是心跳sy&#xff0c;今天为大家带来malloc函数与free函数的用法&#xff0c;我们一起来看看吧&#xff01; 目录 一、malloc函数 &#x1f4ab; 1、⭐️malloc函数对应的头文件⭐️ 2、⭐️malloc函数的作用⭐️ 3…

高职计算机网络实训室

一、高职计算机网络实训室建设的背景 如今&#xff0c;数字化发展已成为国家发展的战略方向&#xff0c;是推动社会进步和经济发展的重要动力。在这一时代背景下&#xff0c;计算机网络技术作为数字化发展的基础设施&#xff0c;其地位和作用愈发凸显。因此&#xff0c;高职院…

Windows中nvm的安装配置和卸载

文章目录 Windows中安装配置&#xff0c;和卸载nvm一、卸载node二、安装vnm三、配置环境&#xff08;配置路径和下载源&#xff09;四、使用nvm安装node五、nvm常见的命令六、nvm的卸载 Windows中安装配置&#xff0c;和卸载nvm 一、卸载node 如果没有node可以直接了跳过该步…

<数据集>Udacity交通目标识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;13239张&#xff08;实际有15000张&#xff0c;但其中1761张无标签的图片被我去除掉&#xff09; 标注数量(xml文件个数)&#xff1a;13239 标注数量(txt文件个数)&#xff1a;13239 标注类别数&#xff1a;11 标注…

全开源TikTok跨境商城源码/TikTok内嵌商城+搭建教程/前端uniapp+后端

多语言跨境电商外贸商城 TikTok内嵌商城&#xff0c;商家入驻一键铺货一键提货 全开源完美运营 海外版抖音TikTok商城系统源码&#xff0c;TikToK内嵌商城&#xff0c;跨境商城系统源码 接在tiktok里面的商城。tiktok内嵌&#xff0c;也可单独分开出来当独立站运营 二十一种…

Tomcat下载安装配置教程(零基础超详细)

「作者简介」&#xff1a;冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础著作 《网络安全自学教程》&#xff0c;适合基础薄弱的同学系统化的学习网络安全&#xff0c;用最短的时间掌握最核心的技术。 Tomcat 1、下载…

Docker 镜像构建报 exec xxx.sh: no such file or directory

问题记录 场景&#xff1a; 处于对nacos docker 部署最新版本的探究&#xff0c;但是nacos/nacos-server镜像拉取不到最新版本&#xff0c;官网也是给出自己构建镜像的方案。 具体步骤很简单&#xff0c;先clone项目&#xff0c;然后签出你要的nacos版本&#xff0c;通过docke…

Java——IO流(二)-(7/7):补充知识:IO框架(什么是框架、什么是IO框架、Commons-io)

目录 什么是框架 什么是IO框架 Commons-io 常用方法 框架下载 框架导入 实例演示 什么是框架 解决某类问题&#xff0c;编写的一套类、接口等&#xff0c;可以理解成一个半成品&#xff0c;大多框架都是第三方研发的。好处&#xff1a;在框架的基础上开发&#xff0c;可…

edge 学习工具包 math solver

简介 推荐微软推出的学习工具中的两项工具&#xff1a;数学求解器和 pdf 阅读器。 打开 edge 学习工具包的方法 &#xff1a;右上角三点-更多工具-学习工具包。 math solver 除了基础的计算求解外&#xff0c;还用图标展示公式&#xff0c;清晰直观。 地址&#xff1a;求解…

Vue 中的 scoped 和 /deep/ 深度选择器

Vue在组件里写 css 给 <style> 标签加上 scoped &#xff0c;比如&#xff1a; <style lang"less" scoped> &#xff0c;这样的 css 就是局部的&#xff0c;不会影响其他组件。 假设引入了一个子组件&#xff0c;并希望在组件中修改子组件的样式&#x…

多波束常用设备的坐标系统

CARIS处理多波束的时候&#xff0c;一般首先要建立船型文件&#xff0c;采集的设备或软件不同&#xff0c;其船型文件也不同&#xff0c;其中最关键就是采集设备和软件的坐标系统。 为了使用方便&#xff0c;不用费力地去查对应的使用手册&#xff0c;现将常用多波束设备和软件…

VMware vSAN 8.0U3 - 存储虚拟化软件

VMware vSAN 8.0U3 - 存储虚拟化软件 vSAN 8 with Express Storage Architecture 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-vsan/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org VMware vSAN 存储虚拟化软…

Covalent Network(CXT)通过社区投票将代币迁移并更名为 CXT,以推动人工智能更深层次的创新

专注于人工智能和 Web3 的模块化数据基础设施 Covalent Network&#xff08;CXT&#xff09;宣布&#xff0c;其治理提案已通过社区投票并顺利实施&#xff0c;即将原生代币 CQT 迁移为新的 CXT 代币&#xff0c;并部署至新的合约。这一关键性转变标志着 Covalent Network&…

Fastjson2使用JSONOObject或者mao转换为JSON字符串时丢失Null值字段

最近在工作中发现问题fastJson转换为JSONString时丢失值为null的问题特此解决。 public class test001 {public static void main(String[] args) {JSONObject jsonObject new JSONObject();jsonObject.put("foo1", "bar");jsonObject.put("foo2&quo…

最新 Kubernetes 集群部署 + Containerd容器运行时 + flannel 网络插件(保姆级教程,最新 K8S 1.28.2 版本)

资源列表 操作系统配置主机名IP所需插件CentOS 7.92C4Gk8s-master192.168.60.143flannel-cni-plugin、flannel、coredns、etcd、kube-apiserver、kube-controller-manager、kube-proxy、 kube-scheduler 、containerd、pause 、crictlCentOS 7.92C4Gk8s-node01192.168.60.144f…

“汇聚全球智慧·引领未来科技”2024南京人工智能展会

南京&#xff0c;这座古老而又现代的城市&#xff0c;自古以来便是江南繁华的代名词。如今&#xff0c;随着科技的飞速发展&#xff0c;南京再次站在了时代的潮头&#xff0c;以其深厚的历史底蕴和不断创新的科技力量&#xff0c;成为了全球瞩目的焦点。而在即将到来的2024年&a…