* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/shm.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <gtest/gtest.h>
#include "utils.h"
#include "log.h"
using namespace testing::ext;
class ShmTest : public ::testing::Test
{
public:
static const char SHM_TEST_STR[];
static const int SHM_TEST_STR_LEN;
};
const char ShmTest::SHM_TEST_STR[] = "hello shmem";
const int ShmTest::SHM_TEST_STR_LEN = sizeof(SHM_TEST_STR);
* @tc.name testShmBasic
* @tc.number SUB_KERNEL_IPC_SHM_ALL_0100
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL0
*/
HWTEST_F(ShmTest, testShmBasic, Function | MediumTest | Level0)
{
const int memSize = 1024;
int shmid;
char *shared = nullptr;
shmid = shmget(static_cast<key_t> IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
if (shmid == -1) {
LOG("shmget errno ,errno = %d", errno);
ADD_FAILURE();
}
pid_t pid = fork();
if (pid < 0) {
LOG("fork errno ,errno = %d", errno);
ADD_FAILURE();
}
if (pid == 0) {
int exitCode = 0;
Msleep(40);
shared = static_cast<char*>(shmat(shmid, nullptr, 0));
if (shared == reinterpret_cast<char*>(-1)) {
LOG("> child: shmat errno = %d", errno);
exit(1);
}
if (strncmp(shared, SHM_TEST_STR, SHM_TEST_STR_LEN) != 0) {
LOG("> child: error strncmp() shared = %s", shared);
exitCode = 1;
}
if ((shmdt(shared)) == -1) {
LOG("> child: shmdt errno = %d", errno);
exit(1);
}
if (shmctl(shmid, IPC_RMID, nullptr) == -1) {
LOG("> child: shmctl errno = %d", errno);
exit(1);
}
exit(exitCode);
}
shared = static_cast<char*>(shmat(shmid, nullptr, 0));
if (shared == (void*)-1) {
LOG("shmat errno ,errno = %d", errno);
ADD_FAILURE();
}
strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN);
if (shmdt(shared) == -1) {
LOG("shmdt errno ,errno = %d", errno);
ADD_FAILURE();
}
Msleep(50);
WaitProcExitedOK(pid);
}
* @tc.name testShmSingleProcess
* @tc.number SUB_KERNEL_IPC_SHM_ALL_0300
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL1
*/
HWTEST_F(ShmTest, testShmSingleProcess, Function | MediumTest | Level1)
{
const int memSize = 1024;
char *shared = nullptr;
int shmid = shmget(static_cast<key_t> IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
if (shmid == -1) {
LOG("shmget errno ,errno = %d", errno);
ADD_FAILURE();
}
shared = static_cast<char*>(shmat(shmid, nullptr, 0));
ASSERT_NE(shared, (void*)-1) << "> shmat errno = " << errno;
strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN);
int re = shmdt(shared);
ASSERT_NE(re, -1) << "> shmdt errno = " << errno;
re = shmctl(shmid, IPC_RMID, nullptr);
ASSERT_NE(re, -1) << "> shmctl errno = " << errno;
}
* @tc.name testShmget
* @tc.number SUB_KERNEL_IPC_SHM_SHMGET_0100
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL0
*/
HWTEST_F(ShmTest, testShmget, Function | MediumTest | Level0)
{
const int memSize = 1024;
int tmp;
int shmid;
int shmidTmp;
int tmpKey = GetRandom(2147483647);
LOG("> tmpKey = %d", tmpKey);
shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno;
tmp = shmctl(shmid, IPC_RMID, nullptr);
ASSERT_NE(tmp, -1) << "shmctl : error : IPC_RMID ";
shmid = shmget(key_t(tmpKey), memSize, 0666 | IPC_CREAT);
ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno;
tmp = shmctl(shmid, IPC_RMID, nullptr);
ASSERT_NE(tmp, -1) << "shmctl : error : IPC_RMID ";
shmid = shmget(key_t(tmpKey), memSize, IPC_EXCL | IPC_CREAT);
ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno;
shmidTmp = shmid;
shmidTmp = shmget(key_t(tmpKey), memSize, IPC_EXCL | IPC_CREAT);
ASSERT_EQ(shmidTmp, -1) << "> shmget : errno = " << errno;
tmp = shmctl(shmid, IPC_RMID, nullptr);
ASSERT_NE(tmp, -1) << "> shmctl : error : IPC_RMID ";
shmid = shmget(key_t(tmpKey), memSize, 0);
ASSERT_EQ(shmid, -1) << "> shmget : errno = " << errno;
shmid = shmget(IPC_PRIVATE, 0, 0666 | IPC_CREAT);
ASSERT_EQ(shmid, -1) << "> shmget : errno = " << errno;
shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
ASSERT_NE(shmid, -1) << "> shmget : errno = " << errno;
tmp = shmctl(shmid, IPC_RMID, nullptr);
ASSERT_NE(tmp, -1) << "> shmctl : error : IPC_RMID";
}
* @tc.name testShmatSHM_REMAP
* @tc.number SUB_KERNEL_IPC_SHM_SHMAT_0100
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL1
*/
HWTEST_F(ShmTest, testShmatSHM_REMAP, Function | MediumTest | Level1)
{
const int memSize = 1024;
int shmid;
char *shared = nullptr;
shmid = shmget(static_cast<key_t> IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
if (shmid == -1) {
LOG("shmget errno ,errno = %d", errno);
ADD_FAILURE();
}
pid_t pid = fork();
if (shmid < 0) {
LOG("fork errno ,errno = %d", errno);
ADD_FAILURE();
}
if (pid == 0) {
Msleep(10);
int exitCode = 0;
shared = static_cast<char*>(shmat(shmid, nullptr, 0));
if (shared == reinterpret_cast<char*>(-1)) {
LOG("> child: shmat 1 : errno = %d", errno);
exit(1);
}
if (shmdt(shared) == -1) {
LOG("> child: shmdt: errno = %d", errno);
exit(1);
}
shared = static_cast<char*>(shmat(shmid, shared, SHM_REMAP));
if (shared == reinterpret_cast<char*>(-1)) {
LOG("> child: shmat 2 : errno = %d", errno);
exit(1);
}
if (strncmp(shared, SHM_TEST_STR, SHM_TEST_STR_LEN) != 0) {
LOG("> child: error strncmp() shared = %s", shared);
exitCode = 1;
}
if ((shmdt(shared)) == -1) {
LOG("> child: shmdt : errno = %d", errno);
exit(1);
}
exit(exitCode);
}
shared = static_cast<char*>(shmat(shmid, nullptr, 0));
ASSERT_NE(shared, (void*)-1) << "> shmat 1 : errno = " << errno;
ASSERT_NE(shmdt(shared), -1) << "> shmdt 1 : errno = " << errno;
shared = static_cast<char*>(shmat(shmid, shared, SHM_REMAP));
ASSERT_NE(shared, (void*)-1) << "> parent: shmat 2 : errno = " << errno;
strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN);
ASSERT_NE(shmdt(shared), -1) << "> parent: shmdt 2 : errno = " << errno;
Msleep(50);
WaitProcExitedOK(pid);
Msleep(50);
ASSERT_NE(shmctl(shmid, IPC_RMID, nullptr), -1) << "> parent: shmctl : errno = " << errno;
}
* @tc.name testShmatSHM_RDONLY
* @tc.number SUB_KERNEL_IPC_SHM_SHMAT_0200
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL0
*/
HWTEST_F(ShmTest, testShmatSHM_RDONLY, Function | MediumTest | Level0)
{
const int memSize = 1024;
int shmid;
char *shared = nullptr;
shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
if (shmid == -1) {
LOG("shmget errno ,errno = %d", errno);
ADD_FAILURE();
}
pid_t pid = fork();
if (pid < 0) {
LOG("fork errno ,errno = %d", errno);
ADD_FAILURE();
}
if (pid == 0) {
int exitCode = 0;
Msleep(10);
shared = static_cast<char*>(shmat(shmid, nullptr, SHM_RDONLY));
if (shared == reinterpret_cast<char*>(-1)){
LOG("> child: shmat : errno = %d", errno);
exitCode = 1;
}
if (strncmp(shared, SHM_TEST_STR, SHM_TEST_STR_LEN) != 0) {
LOG("> child: error strncmp()");
exitCode = 1;
}
shared[0] = '1';
if (shmdt(shared) == -1) {
LOG("> child: shmdt : errno = %d", errno);
exitCode = 1;
}
exit(exitCode);
}
shared = static_cast<char*>(shmat(shmid, nullptr, 0));
EXPECT_NE(shared, (char*)-1) << "shmat : errno = " << errno;
strncpy(shared, SHM_TEST_STR, SHM_TEST_STR_LEN);
int exitCode;
int procStat = CheckProcStatus(pid, &exitCode, 0);
EXPECT_EQ(procStat, 2);
EXPECT_EQ(exitCode, 12) << "target process should exited 255.";
EXPECT_NE(shmdt(shared), -1) << "> shmdt : errno = " << errno;
EXPECT_NE(shmctl(shmid, IPC_RMID, nullptr), -1) << "> shmctl : IPC_RMID errno = " << errno;
}
* @tc.name testShmatSHM_RND
* @tc.number SUB_KERNEL_IPC_SHM_SHMAT_0300
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL0
*/
HWTEST_F(ShmTest, testShmatSHM_RND, Function | MediumTest | Level0)
{
const int memSize = 1024;
int tmp;
int shmid;
void *shared = nullptr;
Msleep(10);
shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
if (shmid == -1) {
LOG("shmget failed+++");
ADD_FAILURE();
}
EXPECT_NE(shmid, -1) << "shmget : errno = " << errno;
shared = shmat(shmid, nullptr, 0);
EXPECT_NE(shared, (void*)-1) << "> shmat : errno = " << errno;
int re = shmdt(shared);
EXPECT_NE(re, -1) << "> shmdt : errno = " << errno;
void *sharedTmp = shared;
sharedTmp = shmat(shmid, sharedTmp, SHM_RND);
EXPECT_NE(sharedTmp, (void*)-1) << "> shmat : error : sharedTmp = " << sharedTmp << "shared = " << shared;
strncpy(static_cast<char*>(sharedTmp), SHM_TEST_STR, SHM_TEST_STR_LEN);
re = shmdt(sharedTmp);
EXPECT_NE(re, -1) << "> shmdt : errno = " << errno;
tmp = shmctl(shmid, IPC_RMID, nullptr);
EXPECT_NE(tmp, -1) << "> shmctl : IPC_RMID errno = " << errno;
}
* @tc.name testShmctl
* @tc.number SUB_KERNEL_IPC_SHM_SHMCTL_0100
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL1
*/
HWTEST_F(ShmTest, testShmctl, Function | MediumTest | Level1)
{
const int memSize = 4096;
struct shmid_ds shmPerm = {0};
int tmp;
int shmid;
LOG("> getuid = %d", getuid());
LOG("> getgid = %d", getgid());
LOG("> getpid = %d", getpid());
Msleep(10);
shmid = shmget(IPC_PRIVATE, memSize, 0666 | IPC_CREAT);
if (shmid == -1) {
LOG("shmget errno = %d \n",errno);
ADD_FAILURE();
}
tmp = shmctl(shmid, IPC_STAT, &shmPerm);
EXPECT_NE(tmp, -1) << "> shmctl : IPC_STAT1 :erron = " << errno;
EXPECT_EQ(shmPerm.shm_lpid, 0);
EXPECT_EQ(shmPerm.shm_nattch, 0);
char *shared = static_cast<char*>(shmat(shmid, nullptr, 0));
EXPECT_NE(shared, (void*)-1) << "> shmat : errno = " << errno;
tmp = shmctl(shmid, IPC_STAT, &shmPerm);
ASSERT_NE(tmp, -1) << "> shmctl : IPC_STAT2 :erron = " << errno;
EXPECT_EQ(shmPerm.shm_perm.__key, 0);
EXPECT_EQ(shmPerm.shm_perm.cuid, geteuid());
EXPECT_EQ(shmPerm.shm_perm.uid, geteuid());
EXPECT_EQ(shmPerm.shm_perm.cgid, getegid());
EXPECT_EQ(shmPerm.shm_perm.gid, getegid());
EXPECT_EQ(shmPerm.shm_perm.mode, 0666);
LOG("> last shmat() time %lld", shmPerm.shm_atime);
LOG("> last shmdt() time %lld", shmPerm.shm_dtime);
EXPECT_EQ(shmPerm.shm_segsz, memSize);
EXPECT_EQ(shmPerm.shm_cpid, getpid());
EXPECT_EQ(shmPerm.shm_lpid, getpid());
EXPECT_EQ(shmPerm.shm_nattch, 1);
tmp = shmctl(shmid, IPC_SET, &shmPerm);
EXPECT_NE(shared, (void*)-1) << "> shmat : errno = " << errno;
tmp = shmdt(shared);
ASSERT_NE(tmp, -1) << "> shmdt : errno = " << errno;
tmp = shmctl(shmid, IPC_RMID, nullptr);
ASSERT_NE(tmp, -1) << "> shmctl : IPC_RMID : errno = " << errno;
}
* @tc.name testShmctlINFO
* @tc.number SUB_KERNEL_IPC_SHM_SHMCTL_0200
* @tc.desc [C- SOFTWARE -0200]
* @tc.type FUNCTION
* @tc.size MEDIUMTEST
* @tc.level LEVEL0
*/
HWTEST_F(ShmTest, testShmctlINFO, Function | MediumTest | Level0)
{
int tmp;
struct shminfo buf = {0};
tmp = shmctl(0, IPC_INFO, (struct shmid_ds *) &buf);
EXPECT_NE(tmp, -1) << "shmctl : IPC_INFO errno = " << errno;
LOG("> shminfo.shmmax = %lu", buf.shmmax);
EXPECT_EQ(buf.shmmin, 1) << "> shminfo.shmmin = " << buf.shmmin;
LOG("> shminfo.shmmni = %lu", buf.shmmni);
LOG("> shminfo.shmseg = %lu", buf.shmseg);
LOG("> shminfo.shmall = %lu", buf.shmall);
struct shm_info info = {0};
tmp = shmctl(0, SHM_INFO, (struct shmid_ds *) &info);
EXPECT_NE(tmp, -1) << "shmctl : SHM_INFO errno = " << errno;
LOG("> shm_info.used_ids = %d", info.used_ids);
LOG("> shm_info.shm_tot = %lu", info.shm_tot);
LOG("> shm_info.shm_rss = %lu", info.shm_rss);
LOG("> shm_info.shm_swp = %lu", info.shm_swp);
LOG("> shm_info.__swap_attempts = %ld", info.__swap_attempts);
LOG("> shm_info.__swap_successes = %ld", info.__swap_successes);
}