Implement a battery of unit tests for SSSD

Introduction

An idea of implementing a battery of unit tests for SSSD(System Service Security Daemon) using cmocka unit test framework is proposed after having a thorough discussion with the SSSD upstream maintainer jhrozek (Jakub Hrozek, #sssd). Actually, it is not just writing better automated test codes but a total refinement of SSSD unit-tests using the cmocka unit testing framework in such a way that it will reduce complexity of unit testing code and making it efficient and provide a good mocking framework for better testing for other developers. Following are the details of the project and the proposed plan of action.

Abstract

Implementing unit tests for SSSD modules using cmocka unit testing framework with proper refactoring, minimum boilerplates and better test coverage. The tests would focus on both covering the new features but mostly on creating test for the core SSSD features, providing developers with better confidence when writing new code

Benefits to Fedora community

  • Contributing the set of unit tests to the SSSD would greatly improve its stability long-term and would help raise confidence when pushing new SSSD versions into Fedora or other distributions.
  • Making SSSD tests less complicated and mock-based unittesting framework would certainly result into an improved testing mechanism and error handling in SSSD.
  • Improvement in the test coverage will result in improvement of code quality of the SSSD.
  • Writing unit-test will help in deeper confidence in the correct behaviour of SSSD code and eventually result in easier resolution of many of the issuses related to SSSD

Project Details

The aim of the project is not just quality assurance of SSSD but to provide a proper implementation of a Unit testing framework rather than just a proof-of-concept. It has far greater goals. SSSD is an important part of the authentication picture for Fedora and other Linux distributions. Unfortunately the current version of SSSD lacks proper unit testing framework for exercising the code which are only reachable when SSSD is connected to the network. This project deals more about writing new tests based on the cmocka framweork and complete refinement of old written SSSD tests using the check framework. The idea here is to dig deeper into testing to provide and maintain long-term robustness and quality of SSSD. It is also important that the new cmocka based tests should be less complex and more efficient. It should have more automated behavior and minimum or no boilerplate code. It should also the coding style set by SSSD coding guidelines.

The other important feature of the framework should be that it should be sustainable long-term in order to support further SSSD improvements. In other words, the tests must be easy to modify when the core SSSD code changes to minimize the time needed to fix the unit tests after architectural changes are performed to the SSSD. This feature would allow the SSSD developers to be more confident of refactoring changes in the daemon itself.

Tools Required During Development

  • the Talloc and Tevent libraries
  • Cmocka library
  • Coverage tool : lcov
  • Vim (IDE)

 

The outline of my work plans

The initial stage of my work deals with becoming familiar with SSSD and learning concepts of cmocka unit-testing framework as mentioned in plan.

The general idea for the unit tests is to cover the two most important parts:

  • retrieving user information
  • authenticating users.

The following diagram gives a pictorial representation of the core components of SSSD and how they interact. Sssdsoc.png
Basically the whole project is divided into two phases, which mimick how the SSSD itself is structured:

  • Phase I : building provider tests
  • Phase II: building responder tests

Because of the large size of the SSSD project, the unit testing framework would focus on the core SSSD features that are enabled in most, if not all, SSSD deployments. In particular, the unit tests would cover only the NSS and PAM responders, while the back end (provider) tests would cover the LDAP users and group code.

Time-line for Milestones

The project is planned to be split across following weekly phases:

[Project Week 1]

Learning the tevent library and the asynchronous model

[Project Week 2]

Learning the tevent library and the async model. Might include some experimenting and reading the code.

[Project Week 3]

Reading the current NSS responder test and augmenting the “get user by name/ID tests”

[Project Week 4]

Adding a similar test for retrieving groups as added for users in the previous step.

[Project Week 5]

Adding another test for the initgroups operation.

[Project Week 6]

Studying the PAM responder code.

[Project Week 7]

Adding a unit test that would cover the PAM responder. Only login (PAM authentication phase) can be covered.

[Project Week 8]

Learning the backend and provider internals. The current DNS update tests might be a good start.

[Project Week 9]

Creating unit tests for retrieving LDAP users. These tests would not be big by themselves, but would include code to be reused by other LDAP tests later

[Project Week 10]

Creating unit tests for storing LDAP groups without nesting (RFC2307)

[Project Week 11]

Creating unit tests for storing LDAP groups with nesting (RFC2307bis)

[Project Week 12]

An extra week to polish the work before submission

Deliverables

Better and improved test codes of SSSD with following features:

  • Tests covering NSS and PAM responders
  • Contribute to the overall code quality by uncovering issues with the unit tests
  • Less complex test infrastructure
  • More efficient testing mechanism
Advertisements

Using Mutex to implement atomicity

/***********************************************************************
* OBJECTIVE : Implement atomicity in case of threads
* FILE NAME : mutex.c
* DATE      : 10-09-2012
* AUTHOR    : Abhishek Kumar Singh
************************************************************************/

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<pthread.h>

/* Gobal data */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;

void *increment(void *);

int main()
{
    pthread_t thread1,thread2;
    int iret1,iret2;

    /* Create two threads that executes independently and parallely */
    iret1 = pthread_create(&thread1,NULL,increment,NULL);
    iret2 = pthread_create(&thread2,NULL,increment,NULL);

    if(iret1 != 0)
        fprintf(stderr,"thread1 can't created");
    if(iret2 != 0 )
        fprintf(stderr,"thread2 can't be created");

    /* Waiting for the threads to terminate */
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);

    return EXIT_SUCCESS;
}

void *increment(void *ptr)
{
    /* Locking Resources for other threads */
    pthread_mutex_lock(&mutex);
    counter ++;
    printf("counter:%d\n",counter);
    pthread_mutex_unlock(&mutex);
    /* Unlocking Resources so that other threads can acess */
    return NULL;
}

Application Of Threads For Solving Problems

I am having operating system as one of the subject this semester. Recently I studied about forking a process and about threads, it’ s really an interesting topic indeed 🙂

I have written code for finding prime numbers between 1 and 100000000 using concept of threading. In this program two threads are getting created which runs independently and simultaneously thus calling  prime_number  function to calculate prime numbers between 1 to 50000 by thread1 and 50001 to 100000000 by thread2 respectively.This really speed up the calculation time as compared to a single program calculating prime numbers between 1 to 100000000.

/*
Objective : Finding all the prime numbers between 1 and 100000000 using threading
File Name : threadprime.c
Date : 8/09/2012
Author : Abhishek Kumar Singh
*/

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<sys/types.h>
#include<unistd.h>
#include<math.h>

void * prime_number(void * ptr);

int main()
{
const size_t limits[2] = {1, 100000000};
const size_t limits_thread1[2] = {2, (limits[1]/2)};
const size_t limits_thread2[2] = {(limits[1]/2 + 1), 10};
int iret1, iret2;

pthread_t thread1, thread2;

/* Create independent threads each of which will execute the prime_number function */
iret1 = pthread_create(&thread1, NULL, prime_number, (void*)limits_thread1);
iret2 = pthread_create(&thread2, NULL, prime_number, (void*)limits_thread2);

/* Wait till the threads are complete */
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);

return EXIT_SUCCESS;
}

void *prime_number(void * ptr)
{
size_t temp;
size_t number;
size_t *limits = (size_t *)ptr;
size_t lower = *limits;
size_t upper = *(limits + 1);

for (number = lower; number <= upper; number++)
{
int flag = 0;
int temp1 = sqrt(number);

for (temp = 2; temp <= temp1; temp++)
{
if (number % temp == 0)
{
flag = 1;
break;
}
}

if (!flag)
printf("%d\n",number);
}

return NULL;
}

Note: compile this program as gcc -pthread threadprime.c -lm

Explaining (int argc, char * argv[])

You all have often came across this term while going through a c or c++ code.I just want to explain this in brief especially for the newbies who find it difficult to understand this concept.

Here argc represents the number of arguments(command line argument) and argv is the argument vector pointing it.
Suppose I am compiling a c code ‘test.c’ so what i give at command line is

$ gcc test.c -o test
$ ./test                                                           //for running executable file test

so here argc=1 as no of command line arguments here is one and argv[0]=./test

similarly if executable is run as

$ ./test <arg1> <arg2>

then here argc=3 and argv[0]=./test ,argv[1]=arg1 and argv[2]=arg2

Below is the c code i have written try it for better understanding of this concept.Have lots of fun with c codes 🙂

#include
main(int argc, char* argv[])
{
int i;
printf("argc = %d\n", argc);
for (i = 0; i < argc; i++)
printf("argv[%d] = %s\n", i, argv[i]);
}